Educational Codeforces Round 51 (Rated for Div. 2) A,B,C,D 题解

版权声明:https://blog.csdn.net/flora715 https://blog.csdn.net/flora715/article/details/82796938

       目录

【A. Vasya And Password】

【B. Relatively Prime Pairs】

【C. Vasya and Multisets】

【D. Bicolorings】


【A. Vasya And Password】

  • 最少的操作使原串变成有数字+大小写字母的串。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
#include<vector>
#include<deque>
#include<cmath>
using namespace std;
typedef unsigned long long ll;

void reads(int &x){ //读入优化(正负整数)
	int fx=1;x=0;char s=getchar();
	while(s<'0'||s>'9'){if(s=='-')fx=-1;s=getchar();}
	while(s>='0'&&s<='9'){x=x*10+s-'0';s=getchar();}
	x*=fx; //正负号
}

char s[1000010];
    
int main(){
    int T; reads(T);
    while(T--){
        scanf("%s",s+1);
        int n=strlen(s+1);
		int cnt1=0,cnt2=0,cnt3=0;
		for(int i=1;i<=n;i++){
		    if(s[i]>='0'&&s[i]<='9') cnt1++;
		    if(s[i]>='a'&&s[i]<='z') cnt2++;
		    if(s[i]>='A'&&s[i]<='Z') cnt3++;
		} 
		if(cnt1==0){
		    if(cnt2>1){
		        for(int i=1;i<=n;i++) 
		            if(s[i]>='a'&&s[i]<='z'){s[i]='1'; break;}
		        cnt2--;
		    } else if(cnt3>1){
		        for(int i=1;i<=n;i++) 
		            if(s[i]>='A'&&s[i]<='Z'){s[i]='1'; break;}
		        cnt3--;
		    }
		}
		if(cnt2==0){
		    if(cnt1>1){
		        for(int i=1;i<=n;i++) 
		            if(s[i]>='1'&&s[i]<='9'){s[i]='a'; break;}
		        cnt1--;
		    } else if(cnt3 > 1){
		        for(int i=1; i<=n; i++) 
		            if(s[i]>='A' && s[i]<='Z'){s[i]='a'; break;}
		        cnt3--;
		    }
		}
		if(cnt3==0){
		    if(cnt1>1){
		        for(int i=1; i<=n; i++) 
		            if(s[i]>='1'&&s[i]<='9'){s[i]='A'; break;}
		        cnt1--;
		    } else if(cnt2>1){
		        for(int i=1;i<=n;i++) 
		            if(s[i]>='a'&&s[i]<='z'){s[i]='A'; break;}
		        cnt2--;
		    }
		}
		printf("%s\n",s+1);
	}
    return 0;
}

【B. Relatively Prime Pairs】

  • 给出一组从l到r的所有整数,(r-l)总是奇数。
  • 将这些数字精确地分成(r-l+1)/2对,使得对于每对i、j的最大公约数等于1。
  • 打印生成的对。如果有多个解决方案,请打印其中任何一个。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
#include<vector>
#include<deque>
#include<cmath>
using namespace std;
typedef unsigned long long ll;

//相邻两数gcd为1

void reads(ll &x){ //读入优化(正负整数)
	int fx=1;x=0;char s=getchar();
	while(s<'0'||s>'9'){if(s=='-')fx=-1;s=getchar();}
	while(s>='0'&&s<='9'){x=x*10+s-'0';s=getchar();}
	x*=fx; //正负号
}
    
int main(){
    ll l,r; reads(l),reads(r); //注意要用ll
    if(l==r){ puts("NO"); return 0; }
    puts("YES");
    for(ll i=l;i<=r-1;i+=2)
    	cout<<i<<" "<<i+1<<endl;
    return 0;
}

【C. Vasya and Multisets】

  • 由n个整数组成的多重集。如果数字x只出现在多重集中一次,
  • 就说它很好。希望将多重集s分成两个多字节a和b(其中一个可能是空的),
  • 使得两集合中好数的数量相同。 输出分组方案(组别 ‘A’ or ’B‘)。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
#include<vector>
#include<deque>
#include<cmath>
#include<map>
using namespace std;
typedef unsigned long long ll;

/*【C】
由n个整数组成的多重集。如果数字x只出现在多重集中一次,就说它很好。
希望将多重集s分成两个多字节a和b(其中一个可能是空的),使得两集合中好数的数量相同。 */

//记录单一元素个数,如果是偶数,隔一个输出一个;如果是奇数,询问出现三次以上的数的个数。

void reads(int &x){ //读入优化(正负整数)
	int fx=1;x=0;char s=getchar();
	while(s<'0'||s>'9'){if(s=='-')fx=-1;s=getchar();}
	while(s>='0'&&s<='9'){x=x*10+s-'0';s=getchar();}
	x*=fx; //正负号
}

int n,a[519];
map<int,int> maps;

int main(){
    int n; reads(n);
    for(int i=1;i<=n;i++) reads(a[i]);
    for(int i=1;i<=n;i++) maps[a[i]]++;
    int cnt[5]={0,0,0,0,0};
    for(int i=1;i<=100;i++) 
        if(maps[a[i]]<3) cnt[maps[a[i]]]++;
        else cnt[3]++; //超过三个,可以分成一边一个,一边>1个
    if((cnt[1]&1)&&(cnt[3]==0)){ puts("NO"); return 0; }
    puts("YES"); int mid=cnt[1]/2;
    if(cnt[1]&1){ //cnt[3]!=0,利用一个出现三次以上的即可
        int p=0;
        for(int i=1;i<=n;i++) //找到第一个出现三次以上的
            if(maps[a[i]]>2){ p=i; break; }
        for(int i=1;i<=n;i++)
            if(maps[a[i]]==1){
                if(mid) putchar('A'),mid--;
                else putchar('B');
            } else if(i!=p) putchar('B');
            else putchar('A');
    } else{ //cnt[3]==0,全部用cnt[1]即可
        for(int i=1;i<=n;i++)
            if(maps[a[i]]==1){
                if(mid) putchar('A'),mid--;
                else putchar('B');
            } else putchar('B');
    }
    return 0;
}

【D. Bicolorings】

  • 一个网格2行n列,此网格的每个单元格应为黑色或白色。
  • 如果两个单元具有共同的边界并且共享相同的颜色,则它们被认为是邻居。
  • 如果存在属于与B相同的组件的邻居A,则两个小区A和B属于一个联通。
  • 如果它具有正好的k个连通,那么我们称之为一个双色块。
  • 计算构成k个双色块的方案数。答案模998244353。

【分析】f[i][j][type] 表示 第i列,已经有j个连通块,状态为上下行间差异。

状态 type: BW,BB,WW,WB( 第i列的 上行~下行 )

状态转移方程:

  • f[i][j][0]=f[i-1][j][0]+f[i-1][j-1][1]+f[i-1][j-1][2]+f[i-1][j-2][3];
  • f[i][j][1]=f[i-1][j][0]+f[i-1][j][1]+f[i-1][j-1][2]+f[i-1][j][3];
  • f[i][j][2]=f[i-1][j][0]+f[i-1][j-1][1]+f[i-1][j][2]+f[i-1][j][3];
  • f[i][j][3]=f[i-1][j-2][0]+f[i-1][j-1][1]+f[i-1][j-1][2]+f[i-1][j][3];
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
#include<vector>
#include<deque>
#include<cmath>
#include<map>
using namespace std;
typedef unsigned long long ll;

/*【D】
一个网格2行和n列,此网格的每个单元格应为黑色或白色。
如果两个单元具有共同的边界并且共享相同的颜色,则它们被认为是邻居。 
如果存在属于与B相同的组件的邻居A,则两个小区A和B属于一个联通。
如果它具有正好的k个连通,那么我们称之为一个双色块。
计算构成k个双色块的方案数。答案模998244353。 */

//f[i][j][type] 第i列,已经有j个连通块,状态为上下行间差异
//type: BW,BB,WW,WB( 第i列的 上行~下行 )
//方程:f[i][j][0]=f[i-1][j][0]+f[i-1][j-1][1]+f[i-1][j-1][2]+f[i-1][j-2][3];
//f[i][j][1]=f[i-1][j][0]+f[i-1][j][1]+f[i-1][j-1][2]+f[i-1][j][3];
//f[i][j][2]=f[i-1][j][0]+f[i-1][j-1][1]+f[i-1][j][2]+f[i-1][j][3];
//f[i][j][3]=f[i-1][j-2][0]+f[i-1][j-1][1]+f[i-1][j-1][2]+f[i-1][j][3];

void reads(int &x){ //读入优化(正负整数)
  int fx=1;x=0;char s=getchar();
  while(s<'0'||s>'9'){if(s=='-')fx=-1;s=getchar();}
  while(s>='0'&&s<='9'){x=x*10+s-'0';s=getchar();}
  x*=fx; //正负号
}

const int mod=998244353;
ll f[2001][2001][4];

int main(){
  int n,k; reads(n); reads(k);
  f[1][2][0]=1; f[1][1][1]=1; 
  f[1][1][2]=1; f[1][2][3]=1;
  for(int i=2;i<=n;i++) //注意:初始化第一列,从第二列开始循环
    for(int j=0;j<=k;j++){
      f[i][j][0]=(f[i-1][j][0]%mod+f[i-1][j-1][1]%mod+f[i-1][j-1][2]%mod+f[i-1][j-2][3]%mod)%mod;
      f[i][j][1]=(f[i-1][j][0]%mod+f[i-1][j][1]%mod+f[i-1][j-1][2]%mod+f[i-1][j][3]%mod)%mod;
      f[i][j][2]=(f[i-1][j][0]%mod+f[i-1][j-1][1]%mod+f[i-1][j][2]%mod+f[i-1][j][3]%mod)%mod;
      f[i][j][3]=(f[i-1][j-2][0]%mod+f[i-1][j-1][1]%mod+f[i-1][j-1][2]%mod+f[i-1][j][3]%mod)%mod;
    } 
  ll ans=(f[n][k][0]%mod+f[n][k][1]%mod+f[n][k][2]%mod+f[n][k][3]%mod)%mod;
  cout<<ans<<endl; return 0;
}

                                      ——时间划过风的轨迹,那个少年,还在等你。

猜你喜欢

转载自blog.csdn.net/flora715/article/details/82796938