【Codeforces #166 Div2】Solutions

  好久没有做CF了手生的很。。。

 

  【A.Beautiful Year】

  http://www.codeforces.com/contest/271/problem/A

  题目大意:四位数都不同的年份被称为“Beautiful Year”,问一个给定年份之后最近的“Beautiful Year”

  模拟就可以了。。。

View Code
 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,问最少操作次数使得存在一行或一列全为质数。

  预处理出每个格子需要多少次操作成为质数,然后求最小行、列和即可。素数筛表即可,注意多筛一些。

View Code
 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

View Code
 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了。。。

View Code
 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个。

View Code
 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 }

 

posted @ 2013-02-14 12:26  Delostik  阅读(320)  评论(0编辑  收藏  举报