【Codeforces #166 Div2】Solutions
好久没有做CF了手生的很。。。
【A.Beautiful Year】
http://www.codeforces.com/contest/271/problem/A
题目大意:四位数都不同的年份被称为“Beautiful Year”,问一个给定年份之后最近的“Beautiful Year”
模拟就可以了。。。
1 #include <iostream> 2 #include <cstdio> 3 #include <cstdlib> 4 #include <cstring> 5 using namespace std; 6 7 int n; 8 bool vis[10]; 9 10 bool check(int x){ 11 memset(vis,false,sizeof(vis)); 12 while(x){ 13 int tmp=x%10; 14 x/=10; 15 if(vis[tmp]) return false; 16 vis[tmp]=true; 17 } 18 return true; 19 } 20 21 int main(){ 22 cin>>n; 23 n++; 24 while(!check(++n)) 25 cout<<n<<endl; 26 }
【B.Prime Matrix】
http://www.codeforces.com/contest/271/problem/B
题目大意:n×m的格子,每次操作可以将一个格子中的数字加1,问最少操作次数使得存在一行或一列全为质数。
预处理出每个格子需要多少次操作成为质数,然后求最小行、列和即可。素数筛表即可,注意多筛一些。
1 #include <iostream> 2 #include <cstdio> 3 #include <cstdlib> 4 #include <cstring> 5 using namespace std; 6 template<class T>inline void gmin(T &a,T b){if(a>b)a=b;} 7 8 int n,m,a[1010][1010],prime[101000],tot,ans=2147483647,sum[1010][1010]; 9 bool vis[200010]; 10 11 int check(int x,int y){ 12 int t=a[x][y]; 13 int low=1,high=tot,mid; 14 while(low<high){ 15 mid=(low+high)>>1; 16 if(prime[mid]<t) low=mid+1; 17 else high=mid; 18 } 19 sum[x][y]=prime[low]-t; 20 } 21 22 int main(){ 23 cin>>n>>m; 24 for(int i=1;i<=n;i++) 25 for(int j=1;j<=m;j++) 26 cin>>a[i][j]; 27 for(int i=2;i<=200010;i++) 28 if(!vis[i]){ 29 for(int j=2;j*i<=200000;j++) 30 vis[j*i]=true; 31 } 32 for(int i=2;i<=200000;i++) 33 if(!vis[i]) prime[++tot]=i; 34 35 for(int i=1;i<=n;i++) 36 for(int j=1;j<=m;j++) 37 check(i,j); 38 for(int i=1;i<=n;i++){ 39 int tmp=0; 40 for(int j=1;j<=m;j++) 41 tmp+=sum[i][j]; 42 gmin(ans,tmp); 43 } 44 for(int i=1;i<=m;i++){ 45 int tmp=0; 46 for(int j=1;j<=n;j++) 47 tmp+=sum[j][i]; 48 gmin(ans,tmp); 49 } 50 cout<<ans<<endl; 51 return 0; 52 }
【C.Secret】
http://www.codeforces.com/contest/271/problem/C
题目大意:n个物品分给k个人,使得每件物品所属的人的编号都不组成等差数列,找出可行方案。
这题做法有很多,随便构造一下就可以了。首先如果k*3<=n的话一定是无解的,因为这样肯定存在一个人拥有少于三个物品,那么必然构成等差数列。
满足之后就构造。可以1...k 1...k k...1,也可以112233...kk 1..k,and so on
1 #include <iostream> 2 #include <cstdio> 3 #include <cstdlib> 4 #include <cstring> 5 using namespace std; 6 7 int n,m; 8 9 int main(){ 10 cin>>n>>m; 11 if(m*3>n){ 12 cout<<-1<<endl; 13 return 0; 14 } 15 for(int i=1;i<=m;i++) 16 cout<<i<<" "<<i<<" "; 17 for(int i=1;i<=m;i++) 18 cout<<i<<" "; 19 for(int i=1;i<=n-3*m;i++) cout<<"1 "; 20 return 0; 21 }
【D.Good Substrings】
http://www.codeforces.com/contest/271/problem/D
题目大意:存在不多于k个"坏"字母的字符串叫做“Good Substring”,问字符串s中有多少个不同子串是"Good Substring"。
复杂度不高,可以预处理前缀和(坏字母个数),然后枚举左右端点,哈希判重,这里直接用map了。。。
1 #include <iostream> 2 #include <string> 3 #include <map> 4 using namespace std; 5 6 const long long BASE=29; 7 const long long MOD=10000000000000000LL; 8 map<long long,bool> m; 9 long long base[2000],hash; 10 int k,cnt; 11 string s,good; 12 13 int main(){ 14 cin>>s>>good>>k; 15 int len=s.length(); 16 base[0]=1; 17 for(int i=1;i<=len;i++) 18 base[i]=(base[i-1]*BASE)%MOD; 19 for(int i=0;i<len;i++){ 20 hash=cnt=0; 21 for(int j=i;j<len;j++){ 22 cnt+=good[s[j]-'a']=='0'; 23 if(cnt>k) break; 24 hash=(hash+(long long)(s[j]-'a'+1)*base[j-i])%MOD; 25 m[hash]=true; 26 } 27 } 28 cout<<m.size()<<endl; 29 return 0; 30 }
【E.Three Horses】
http://www.codeforces.com/contest/271/problem/E
题目大意:有三种转换(具体看题),问有多少种(x,y),x<=y<=m能通过转换得到所有二元组(1,an)
思路来自cxlove blog:http://blog.csdn.net/acm_cxlove/article/details/8579542
从二元组(x,y)的差d=y-x来考虑。
对于第一个操作(x,y)->(x+y),(x,y)->(y,2y-x)->(x,2y-x)->(2x-2,2y-2)->(x-1,y-1),由此可知一个差为d的二元组(x,y)可以推出所有差为d的二元组(x',y')。
对于第二个操作,(x,x+d)->(x/2,x/2+d/2),d'=d/2,差减半,由此可知一个差为d的二元组可以退出所有差为d^(2k)的所有二元组(x',y')。
对于第三个操作,(x,x+d1)&(x+d1,x+d1+d2)->(x,x+d1+d2),差为两个二元组差的和,由此可知由一个差为d的二元组(x,y)可以推出所有差为kd的二元组(x',y')。
综上,我们可以找出所有可以推出目标二元组的可能的“差”,如果差为d,且x<=y<=m,则差为d的可能的初始二元组有m-d个。
1 #include <iostream> 2 using namespace std; 3 4 int n,m,a,gcd; 5 long long ans; 6 7 int GCD(int a,int b){ 8 return b==0?a:GCD(b,a%b); 9 } 10 11 int main(){ 12 cin>>n>>m; 13 for(int i=0;i<n;i++){ 14 cin>>a; 15 gcd=GCD(gcd,a-1); 16 } 17 while(!(gcd&1)) gcd>>=1; 18 for(int i=1;i*i<=gcd;i++) 19 if(!(gcd%i)){ 20 for(int j=i;j<m;j<<=1) ans+=m-j; 21 if(i*i<gcd) 22 for(int j=gcd/i;j<m;j<<=1) ans+=m-j; 23 } 24 cout<<ans<<endl; 25 return 0; 26 }