zoukankan      html  css  js  c++  java
  • Educational Codeforces Round 83 (Rated for Div. 2)

    A. Two Regular Polygons

    题意:给两个数m<n,判断能否选择正n边形的m个端点构成正m边形。

    思路:构造出的正m边形的每条边对应原正n边形的边的数目是相同的,所以只需要判断n能否被m整除即可。

     1 #include<bits/stdc++.h>
     2 #define LL long long
     3 #define dl double
     4 void rd(int &x){
     5  x=0;int f=1;char ch=getchar();
     6  while(ch<'0' || ch>'9'){if(ch=='-')f=-1;ch=getchar();}
     7  while(ch<='9' && ch>='0')x=x*10+ch-'0',ch=getchar();x*=f;
     8 }
     9 void lrd(LL &x){
    10  x=0;int f=1;char ch=getchar();
    11  while(ch<'0' || ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    12  while(ch<='9' && ch>='0')x=x*10+ch-'0',ch=getchar();x*=f;
    13 }
    14 const int INF=1e9;
    15 const LL LINF=1e18;
    16 using namespace std;
    17 int T,n,m;
    18 int main(){
    19  rd(T);
    20  while(T--){
    21   rd(n);rd(m);
    22   if(n % m)printf("NO
    ");
    23   else printf("YES
    ");
    24  }
    25  return 0;
    26 }
    27 /**/
    View Code

    反思:记住这个小小的结论吧。

    B. Bogosort

    题意:给n个数,将它们重新排列使得对于所有i<j,j-aj!=i-ai,输出重新排列后的数组,任意输出一个即可。

    思路:从大到小排序即可。

     1 #include<bits/stdc++.h>
     2 #define LL long long
     3 #define dl double
     4 void rd(int &x){
     5  x=0;int f=1;char ch=getchar();
     6  while(ch<'0' || ch>'9'){if(ch=='-')f=-1;ch=getchar();}
     7  while(ch<='9' && ch>='0')x=x*10+ch-'0',ch=getchar();x*=f;
     8 }
     9 void lrd(LL &x){
    10  x=0;int f=1;char ch=getchar();
    11  while(ch<'0' || ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    12  while(ch<='9' && ch>='0')x=x*10+ch-'0',ch=getchar();x*=f;
    13 }
    14 const int INF=1e9;
    15 const LL LINF=1e18;
    16 const int N=105;
    17 using namespace std;
    18 int T,n;
    19 int a[N];
    20 bool cmp(int x,int y){return x>y;}
    21 int main(){
    22 // freopen("in.txt","r",stdin);
    23  rd(T);
    24  while(T--){
    25   rd(n);
    26   for(int i=1;i<=n;i++)rd(a[i]);
    27   sort(a+1,a+n+1,cmp);
    28   for(int i=1;i<=n;i++)printf("%d ",a[i]);
    29   puts("");
    30  }
    31  return 0;
    32 }
    33 /**/
    View Code

    C. Adding Powers

    题意:给n个数,问能否通过以下操作将初始全为0的数组变成这n个数。第i次操作可以将一个数加上k^i或者跳过。

    思路:将n个数都看成k进制数字,看每一位之和是否都小于等于1即可。

     1 #include<bits/stdc++.h>
     2 #define LL long long
     3 #define dl double
     4 void rd(int &x){
     5  x=0;int f=1;char ch=getchar();
     6  while(ch<'0' || ch>'9'){if(ch=='-')f=-1;ch=getchar();}
     7  while(ch<='9' && ch>='0')x=x*10+ch-'0',ch=getchar();x*=f;
     8 }
     9 void lrd(LL &x){
    10  x=0;int f=1;char ch=getchar();
    11  while(ch<'0' || ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    12  while(ch<='9' && ch>='0')x=x*10+ch-'0',ch=getchar();x*=f;
    13 }
    14 const int INF=1e9;
    15 const LL LINF=1e18;
    16 const int N=35;
    17 using namespace std;
    18 int T;
    19 int n,k;
    20 LL a[N];
    21 int main(){
    22 // freopen("in.txt","r",stdin);
    23  rd(T);
    24  while(T--){
    25   rd(n);rd(k);
    26   for(int i=1;i<=n;i++)lrd(a[i]);
    27   bool flg=0;
    28   for(int i=0;i<=100;i++){
    29    int cnt=0;
    30    for(int j=1;j<=n;j++)cnt+=a[j]%k,a[j]/=k;
    31    if(cnt > 1)flg=1;
    32   }
    33   if(flg)printf("NO
    ");
    34   else printf("YES
    ");
    35  }
    36  return 0;
    37 }
    38 /**/
    View Code

    D. Count the Arrays

    题意:计算满足以下条件的数组的数目。长度为n(2e5),所有数都在1~m(2e5)(m>=n)之间,存在一个i使得前i个数严格递增,i~n严格递减,有且只有两个数相等。对998244353取模。

    思路:组合数计数的问题。考虑已经找到了那两个相等的数字的下标ij,并且他们之间的数字也已经选择好了,那么他们中间的数字的排列方式有C(j-i-2,0)+C(j-i-2,1)+...+C(j-i-2,j-i-2)种,因为最高点的数值是确定的,这个过程是在枚举最高点左面选择哪些数字,因为一旦选择好了排列方式是唯一的。共计2^(j-i-2)种。而对于ij两边的数字,也是类似的情况,只需要枚举左面选的那些即可,共计2^(n-j+i-1)种,也就是说,在ij确定,他们之间和两边的数字都确定的情况下,共有2^(n-3)种排列方式,与ij的具体值无关。而我们只需要从m个数字种选出n-1个数,再选定相等的两个数字之后,ij之间和两边的数字集合其实也是确定了的,而根据上面的计算共计2^(n-3)种,同时不能选取最大值作为相等的两数字,也就是说最终的方案数为C(m,n-1)*(n-2)*2^(n-3)。

     1 #include<bits/stdc++.h>
     2 #define LL long long
     3 #define dl double
     4 void rd(int &x){
     5  x=0;int f=1;char ch=getchar();
     6  while(ch<'0' || ch>'9'){if(ch=='-')f=-1;ch=getchar();}
     7  while(ch<='9' && ch>='0')x=x*10+ch-'0',ch=getchar();x*=f;
     8 }
     9 void lrd(LL &x){
    10  x=0;int f=1;char ch=getchar();
    11  while(ch<'0' || ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    12  while(ch<='9' && ch>='0')x=x*10+ch-'0',ch=getchar();x*=f;
    13 }
    14 const int INF=1e9;
    15 const LL LINF=1e18;
    16 const int N=2e5+10;
    17 const int mod=998244353;
    18 using namespace std;
    19 int n,m;
    20 int fac[N],pw[N];
    21 int fast_pow(int x,int y){
    22  int ans=1;
    23  while(y){
    24   if(y&1)ans=1ll*ans*x%mod;
    25   x=1ll*x*x%mod;y>>=1;
    26  }
    27  return ans;
    28 }
    29 int main(){
    30 // freopen("in.txt","r",stdin);
    31  rd(n);rd(m);fac[0]=1;pw[0]=1;
    32  for(int i=1;i<=max(n,m);i++)fac[i]=1ll*fac[i-1]*i%mod,pw[i]=pw[i-1]*2%mod;
    33  if(n == 2)printf("0
    ");
    34  else {
    35   int ans=1ll*fast_pow(fac[n-1],mod-2)*fast_pow(fac[m-n+1],mod-2)%mod*fac[m]%mod*(n-2)%mod*pw[n-3]%mod;
    36   printf("%d
    ",ans);
    37  }
    38  return 0;
    39 }
    40 /**/
    View Code

    反思:我在推出2^(n-3)之后一直没有进展,因为我一直觉得要在m-1个数字中选出ij之间的数字,而这又和ij的具体位置有关了,再选择出两边的数字,得到的式子根本无法化简,而事实上完全不需要那么复杂。可能这就是组合数的魅力吧。

    E. Array Shrinking

    题意:n(500)个数字,每次可以将相邻的两个相等数字合并为一个数字,并且这个数字的数值等于原数字+1,求最终这个序列最短是多少。

    思路:求最短,dp,500的范围,区间dp。基本确定算法后考虑怎么实现。自然而然想到f[i][j]表示i~j最短多短,最终答案就是f[1][n],考虑如何转移。直接枚举中间的k进行转移,那么对于合并的情况如何考虑呢?我们发现如果要合并,合并的两个区间的f一定是1,不然如果可以合并的话,他们的子区间也一定可以进行合并,所以记录一下f为1的区间当前的值为多少进而进行f为1的区间之间的合并即可。因为区间dp是先对长度小的区间dp,所以可以保证处理ij时他们区间内可以合并的情况已经全部计算在内了。

     1 #include<bits/stdc++.h>
     2 #define LL long long
     3 #define dl double
     4 void rd(int &x){
     5  x=0;int f=1;char ch=getchar();
     6  while(ch<'0' || ch>'9'){if(ch=='-')f=-1;ch=getchar();}
     7  while(ch<='9' && ch>='0')x=x*10+ch-'0',ch=getchar();x*=f;
     8 }
     9 void lrd(LL &x){
    10  x=0;int f=1;char ch=getchar();
    11  while(ch<'0' || ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    12  while(ch<='9' && ch>='0')x=x*10+ch-'0',ch=getchar();x*=f;
    13 }
    14 const int INF=1e9;
    15 const LL LINF=1e18;
    16 const int N=505;
    17 int n,a[N];
    18 int f1[N][N],f2[N][N]; 
    19 using namespace std;
    20 int main(){
    21 // freopen("in.txt","r",stdin);
    22  rd(n);for(int i=1;i<=n;i++)rd(a[i]),f1[i][i]=1,f2[i][i]=a[i];
    23  for(int l=2;l<=n;l++){
    24   for(int i=1;i+l-1<=n;i++){
    25    int j=i+l-1;f1[i][j]=0x7fffffff;
    26    for(int k=i;k<=j;k++){
    27     f1[i][j]=min(f1[i][j],f1[i][k]+f1[k+1][j]);
    28     if(f1[i][k] == 1 && f1[k+1][j] == 1 && f2[i][k] == f2[k+1][j])f1[i][j]=1,f2[i][j]=f2[i][k]+1;
    29    }
    30   }
    31  }
    32  printf("%d
    ",f1[1][n]);
    33  return 0;
    34 }
    35 /**/
    View Code
  • 相关阅读:
    Java实现第九届蓝桥杯付账问题
    Java实现第九届蓝桥杯付账问题
    Java实现第九届蓝桥杯星期一
    Java实现第九届蓝桥杯星期一
    Java实现第九届蓝桥杯倍数问题
    Java实现第九届蓝桥杯倍数问题
    Java实现第九届蓝桥杯倍数问题
    Java实现第九届蓝桥杯倍数问题
    Java实现第九届蓝桥杯倍数问题
    Java实现第九届蓝桥杯三体攻击
  • 原文地址:https://www.cnblogs.com/hyghb/p/12489029.html
Copyright © 2011-2022 走看看