Codeforces Round #520 (Div. 2) A B C D
A. A Prank
題目連結:http://codeforces.com/contest/1062/problem/A
題目大意:n個數,輸入n個數,然後對於這些數,看最多能夠擦除多少個數,還能還原出原陣列。
這些數範圍:1~1000。
方法:下標相減==裡面的元素值相減則是能夠刪掉的,然後特判一下頭和尾(取其中能夠刪除最多的元素)
//#pragma comment(linker, "/STACK:1024000000,1024000000") #include<stdio.h> #include<string.h> #include<math.h> #include<stdlib.h> //#include<map> //#include<set> #include<deque> #include<queue> #include<stack> #include<bitset> #include<string> #include<fstream> #include<iostream> #include<algorithm> using namespace std; #define ll long long //#define max(a,b) (a)>(b)?(a):(b) //#define min(a,b) (a)<(b)?(a):(b) #define clean(a,b) memset(a,b,sizeof(a))// ˮӡ //std::ios::sync_with_stdio(false); const int MAXN=1e5+5; const ll INF=1e18; const ll mod=1e9+7; int arr[MAXN]; int main() { std::ios::sync_with_stdio(false); int n; while(cin>>n) { for(int i=1;i<=n;++i) cin>>arr[i]; int ans=0,res=0; int res1=0,res2=0;//頭和尾的可刪除元素個數 for(int i=1,j=1;i<=n;++i) { if((arr[i]-arr[j])==i-j)//刪除一個區間 { if(i-j>1) res++; } else//到該點結束 { if(arr[j]==1&&i-j>1&&j==1)//特判1~i區間 res1=res+1; ans=max(ans,res);//取最大的區間 j=i;//重新整理 res=0; } } if(arr[n]==1000&&arr[n-1]==999)//特判末尾區間 res2=res+1; if(arr[1]==1&&arr[n]==n)//特判從頭到尾1~n res1=n-1; ans=max(ans,res); ans=max(ans,res1); ans=max(ans,res2); cout<<ans<<endl; } }
B. Math
題目連結:http://codeforces.com/contest/1062/problem/B
題目大意:給出一個n,然後有兩種操作,1.乘上一個數 2.對這個數開平方。求只用這兩個操作得出的最小值,並且輸出操作次數。
思路:把這些數的素因子提取出來,因為只能開根,因此如果素因子的次冪都是1的話就是最小值了,答案就是所有的素因子的乘積,
至於此樹,所以我們可以首先將它乘上一個數,使得所有的素因子的次冪都是2的倍數,然後開2的倍數的平方即可
//#pragma comment(linker, "/STACK:1024000000,1024000000") #include<stdio.h> #include<string.h> #include<math.h> #include<stdlib.h> //#include<map> //#include<set> #include<deque> #include<queue> #include<stack> #include<bitset> #include<string> #include<fstream> #include<iostream> #include<algorithm> using namespace std; #define ll long long //#define max(a,b) (a)>(b)?(a):(b) //#define min(a,b) (a)<(b)?(a):(b) #define clean(a,b) memset(a,b,sizeof(a))// ˮӡ //std::ios::sync_with_stdio(false); const int MAXN=1e6+5; const ll INF=1e18; const ll mod=1e9+7; int vis[MAXN]; int main() { std::ios::sync_with_stdio(false); int n; while(cin>>n) { clean(vis,0); int ans=1; for(int i=2;i<=n;++i)//求素因子 { if(n%i==0) ans=ans*i; while(n%i==0)//求出素因子的次冪 { vis[i]++; n=n/i; } } if(n>1) vis[n]++; int maxnum=0; for(int i=1;i<MAXN;++i)//找出最大的那個次冪 maxnum=max(maxnum,vis[i]); int i=1,oper=0; while(i<maxnum)//判斷開平方多少次 { i=i<<1; oper++; } maxnum=i; //乘上去 int f=0;//是否不用乘 for(int j=1;j<MAXN;++j) { if(maxnum!=vis[j]&&vis[j])//要乘以一個數 { f=1; break; } } if(f)//要乘+1 cout<<ans<<" "<<oper+1<<endl; else//不用乘 cout<<ans<<" "<<oper<<endl; } }
C. Banh-mi
題目連結:http://codeforces.com/contest/1062/problem/C
題目大意:給出n個長度的01串和q次詢問,對於每次詢問,輸入一個區間 l,r,然後找能夠按要求的出的最大值,
要求:對於l~r區間的數,取出一個數,然後其他數都加上取出的這個數的值,問最多能取出數的sum最大是多少。
思路:因為是01串,我們每次取最大的就能保證加的最大,稍微模擬一下就可以推出來
MAXsum=2^1的個數的-1+2^1的個數*2^0的個數
特判一下從頭開始的:
//#pragma comment(linker, "/STACK:1024000000,1024000000") #include<stdio.h> #include<string.h> #include<math.h> #include<stdlib.h> //#include<map> //#include<set> #include<deque> #include<queue> #include<stack> #include<bitset> #include<string> #include<fstream> #include<iostream> #include<algorithm> using namespace std; #define ll long long //#define max(a,b) (a)>(b)?(a):(b) //#define min(a,b) (a)<(b)?(a):(b) #define clean(a,b) memset(a,b,sizeof(a))// ˮӡ //std::ios::sync_with_stdio(false); const int MAXN=1e5+5; const ll INF=1e18; const ll mod=1e9+7; int arr[MAXN]; ll res[MAXN]; int main() { std::ios::sync_with_stdio(false); int n,q; string s; res[0]=1; for(int i=1;i<MAXN;++i) res[i]=(res[i-1]*2)%mod;//2的i次冪預處理出來 while(cin>>n>>q) { cin>>s; int len=s.size(); arr[0]=(s[0]=='1')?1:0; for(int i=1;i<len;++i) arr[i]=arr[i-1]+s[i]-'0';//獲得1的個數 int l,r; while(q--) { cin>>l>>r; l--,r--; if(l) //區間 { ll x=res[arr[r]-arr[l-1]]-1;// ll y=res[r-l+1-(arr[r]-arr[l-1])]; cout<<(x*y)%mod<<endl; } else//從第一個開始 { ll x=res[arr[r]]-1;// ll y=res[r-l+1-(arr[r])]; cout<<(x*y)%mod<<endl; } } } }
D. Fun with Integers
題目連結:http://codeforces.com/contest/1062/problem/D
好水的一道題啊!就是題目不好看懂,看懂之後就超簡單!!
題目大意:給一個數n,然後找裡面所有滿足(2≤|a|,|b|≤n)的一對a和b,然後再找出x滿足1<|x| 和 (a⋅x=b||b⋅x=a)
然後看樣例,發現複數和正數是分開算的,於是對於每一對a,b都有四個答案,遍歷一遍加起來即可:
int main()
{
std::ios::sync_with_stdio(false);
int n;
while(cin>>n)
{
ll ans=0;
for(int i=2;i<=n;++i)
{
for(int j=2;j*i<=n;++j)
ans+=j*4;
}
cout<<ans<<endl;
}
}