Codeforces 379D. New Year Letter【动态规划、暴力枚举】
2014-08-23 22:25
357 查看
题目大意:
给出如下定义: s(n)=s(n-2)+s(n-1),其中s为字符串,+为串联,比如s1="ab",s2="cd",s1+s2="abcd",s2+s1="cdab"。给出k,x,n,m,求满足使字符串s(k)中子串“AC”的个数恰好等于x的s1,s2字符串,如果有多种可能,随意输出。
做法:
我们将“AC”其分成两个部分,一种是在s1,s2内部的“AC”,一种是在s1,s2的两端,由s1,s2结合而成的“AC”。由于s(k)一定是由很多个s1,s2串联而成,串联处可能是s1s2,s2s1,s2s2三种。
如此,我们需要知道s(k)中s1,s2的个数,以及s1s2,s2s1,s2s2三种串联方式的分别的数量,利用动态规划即可求出;最后暴力枚举出可能的结果。遇到可能的情况即可跳出枚举,输出答案,具体做法见代码。
代码:
#include <iostream> #include <cstdio> #include <algorithm> #include <cstring> #define N 55 using namespace std; struct aa { long long fir,las,_12,_22,_21,v; }dp ;//字符串信息结构体,fir,las表示当前结构体头和尾分别是s1还是s2,__12为当前字符串由s1s2串联成的数量,其他的变量类似,v为当前字符串中s2的个数 long long k,x,n,m; char s1[N*2],s2[N*2]; long long n1,n2; int main() { scanf("%I64d%I64d%I64d%I64d",&k,&x,&n,&m); // 初始化 dp[2].v=1,dp[2].fir=2,dp[2].las=2,dp[2]._12=dp[2]._22=dp[2]._21=0; dp[3].v=1,dp[3].fir=1,dp[3].las=2,dp[3]._12=1,dp[3]._22=dp[3]._21=0; for(long long i=4;i<=k;i++) { dp[i].v=dp[i-1].v+dp[i-2].v; dp[i]._12=dp[i-1]._12+dp[i-2]._12; dp[i]._22=dp[i-1]._22+dp[i-2]._22; dp[i]._21=dp[i-1]._21+dp[i-2]._21; dp[i].fir=dp[i-2].fir,dp[i].las=dp[i-1].las; if(dp[i-1].fir==1&&dp[i-2].las==2) dp[i]._21++; if(dp[i-1].fir==2&&dp[i-2].las==2) dp[i]._22++; if(dp[i-1].fir==2&&dp[i-2].las==1) dp[i]._12++; } n1=dp[k-1].v,n2=dp[k].v; long long __12=dp[k]._12; long long __22=dp[k]._22; long long __21=dp[k]._21; //枚举开始: long long tail1=n/2,tail2=m/2; long long ans1=-1,ans2=-1; long long flag=0;//记录答案为哪种情况,为0则代表没有符合要求的s1,s2 for(long long i=0;i<=tail1;i++) { for(long long j=0;j<=tail2;j++) { if(i*n1+j*n2>x) break; //如果大于x则没必要枚举下去 if(i*n1+j*n2==x){ans1=i,ans2=j,flag=1;break;} if(__12 && i*n1+j*n2+__12==x && !(i*2==n||j*2==m)){ans1=i,ans2=j,flag=12;break;} if(__22 && i*n1+j*n2+__22==x && !(j*2==m||j*2+1==m)){ans1=i,ans2=j,flag=22;break;} if(__21 && i*n1+j*n2+__21==x && !(i*2==n||j*2==m)){ans1=i,ans2=j,flag=21;break;} if(__21 && __22 && i*n1+j*n2+__21+__22==x && !(i*2==n||j*2==m||j*2+1==m)){ans1=i,ans2=j,flag=21+22;break;} if(__22 && __12 && i*n1+j*n2+__22+__12==x && !(i*2==n||j*2==m||j*2+1==m)){ans1=i,ans2=j,flag=12+22;break;} if(__21 && __12 && __22 && i*n1+j*n2+__21+__12+__22==x && !(i*2==n||j*2==m||j*2+1==m||i*2+1==n)){ans1=i,ans2=j,flag=21+22+12;break;} //没有必要判断__21__12的情况,当此情况满足的时候,__21__12__22一定是满足的。 } if(flag) break;//一旦找到答案,就跳出 } long long i=0; if(!flag) printf("Happy new year!\n"); else// 分情况分别赋值给两个字符串 { if(flag==1){ for(i=0;i<ans1*2;i++) s1[i++]='A',s1[i]='C'; for(long long j=i;j<n;j++) s1[j]='B'; for(i=0;i<ans2*2;i++) s2[i++]='A',s2[i]='C'; for(long long j=i;j<m;j++) s2[j]='B'; } else if(flag==12){ for(i=0;i<ans1*2;i++) s1[i++]='A',s1[i]='C'; for(long long j=i;j<n;j++) s1[j]='B'; s1[n-1]='A';s2[0]='C'; for(i=1;i<ans2*2+1;i++) s2[i++]='A',s2[i]='C'; for(long long j=i;j<m;j++) s2[j]='B'; } else if(flag==22){ s2[0]='C'; for(i=1;i<ans2*2+1;i++) s2[i++]='A',s2[i]='C'; for(long long j=i;j<m;j++) s2[j]='B'; s2[m-1]='A'; for(i=0;i<ans1*2;i++) s1[i++]='A',s1[i]='C'; for(long long j=i;j<n;j++) s1[j]='B'; } else if(flag==21){ s1[0]='C'; for(i=1;i<ans1*2+1;i++) s1[i++]='A',s1[i]='C'; for(long long j=i;j<n;j++) s1[j]='B'; for(i=0;i<ans2*2;i++) s2[i++]='A',s2[i]='C'; for(long long j=i;j<m;j++) s2[j]='B'; s2[m-1]='A'; } else if(flag==22+21){ s2[0]='C'; for(i=1;i<ans2*2+1;i++) s2[i++]='A',s2[i]='C'; for(long long j=i;j<m;j++) s2[j]='B'; s2[m-1]='A';s1[0]='C'; for(i=1;i<ans1*2+1;i++) s1[i++]='A',s1[i]='C'; for(long long j=i;j<n;j++) s1[j]='B'; } else if(flag==22+12){ s2[0]='C'; for(i=1;i<ans2*2+1;i++) s2[i++]='A',s2[i]='C'; for(long long j=i;j<m;j++) s2[j]='B'; s2[m-1]='A'; for(i=0;i<ans1*2;i++) s1[i++]='A',s1[i]='C'; for(long long j=i;j<n;j++) s1[j]='B'; s1[n-1]='A'; } else if(flag==22+12+21){ s2[0]='C'; for(i=1;i<ans2*2+1;i++) s2[i++]='A',s2[i]='C'; for(long long j=i;j<m;j++) s2[j]='B'; s2[m-1]='A';s1[0]='C'; for(i=1;i<ans1*2+1;i++) s1[i++]='A',s1[i]='C'; for(long long j=i;j<n;j++) s1[j]='B'; s1[n-1]='A'; } } cout<<s1<<endl; cout<<s2<<endl; return 0; }
相关文章推荐
- Codeforces 372B. Counting Rectangles is Fun【动态规划,暴力枚举】(lowbit()小用法)
- codeforces 675B B. Restoring Painting(暴力枚举)
- Codeforces 791A Bear and Big Brother(暴力枚举,模拟)
- Codeforces 426 B Sereja and Mirroring【暴力枚举+模拟】水题
- CodeForces 699B——One Bomb(预处理,暴力枚举)
- Codeforces 425A Sereja and Swaps(暴力枚举)
- Codeforces 626D Jerry's Protest(暴力枚举+概率)
- COdeforces 479A - Expression (暴力枚举即可)
- CodeForces 379D 暴力 枚举
- Codeforces 673C Bear and Colors【暴力枚举】
- codeforces 385d bear and floodlight【状压DP之暴力枚举】
- Codeforces 828B Black Square【暴力枚举+二维前缀和】
- codeforces 599D. Spongebob and Squares【推公式+暴力枚举】
- Codeforces 868C - Qualification Rounds 【状态压缩+暴力枚举】
- codeforces 908 C. New Year and Curling【暴力枚举+图解】
- codeforces 724B 暴力+枚举
- Codeforces 724B Batch Sort(暴力枚举)
- CodeForces 496D Tennis Game (暴力枚举)
- CodeForces 593A 2Char(暴力枚举26个字母的组合)
- codeforces 324# E. Anton and Ira (暴力枚举+贪心)