【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 }

 

你可能感兴趣的:(codeforces)