zoukankan      html  css  js  c++  java
  • 【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 }
  • 相关阅读:
    max-points-on-a-line
    evaluate-reverse-polish-notation
    minimum-depth-of-binary-tree
    ML&MLDS笔记:偏差 vs 方差
    机器人的运动范围
    矩阵中的路径
    滑动窗口的最大值
    数据流中的中位数
    1.微服务架构设计(英文-起源)
    5.如何复制一个文件(编程)
  • 原文地址:https://www.cnblogs.com/Delostik/p/2911197.html
Copyright © 2011-2022 走看看