1 条题解
-
0
这是一道动态规划的题目。
首先判断是否存在这个石碑,设现在需要找正好有 个,长度为 的石碑,则一共有 个石碑,而所有可行的数量则为 个,设这个为 ,也写为 ,其中回文的数量,也就是前面一半和后面一半完全一样,因此就是 $xj_{\lceil{\frac{n}{2}}\rceil,\lfloor{\frac{k}{2}}\rfloor}$,设这个数量为 ,则答案为 ,如果 大于这个,就可以直接输出超过的答案。
然后进行动态规划,我们每一位进行筛选,设走到了第 位,则先假设 ,然后进行动态规划求出到目前位置 序列的可行数量,没有确定或者假设的则 和 都可以,然后可以从左和右同时进行,设现在是左边第 位,则右边是第 位,如果左边和右边一样,则不确定能不能,如果左边是 ,右边是 ,则之后一定可以,如果左边是 ,右边是 ,而且不一定可以,则一定不可以。然后可以进行动态规划,方式见代码,设最后答案为 ,如果 ,则代表这一位是 ,然后 减去 ,否则是 。复杂度 。
代码:
#include<bits/stdc++.h> using namespace std; long long ba[65][65],c[65][65],dp[65][65][4][2],hf; int main(){ for(long long j=0;j<=60;j++){ c[j][0]=1;ba[j+1][0]=1; for(long long k=1;k<=j;k++){ c[j][k]=c[j-1][k]+c[j-1][k-1];ba[j+1][k]=c[j][k]+ba[j+1][k-1]; } } long long n,l,i;cin>>n>>l>>i; if(i>ba[n][l]+ba[(n+1)/2][l/2]){ cout<<"NO SUCH STONE"; }else{ string s; for(long long j=0;j<n;j++){ s+='2'; } for(long long v=0;v<n;v++){ s[v]='0';long long all=0; for(long long p=0;p<4;p++){ dp[0][0][p][0]=dp[0][0][p][1]=0; if(p==2){ continue; } if(s[0]=='2' || s[0]-48==p/2){ if(s[n-1]=='2' || s[n-1]-48==p%2){ if(p==1){ dp[0][0][p][1]=1; }else{ dp[0][0][p][0]=1; } } } } for(long long k=1;k<(n+1)/2;k++){ for(long long p=0;p<=l;p++){ for(long long q=0;q<4;q++){ dp[k][p][q][0]=dp[k][p][q][1]=0; if(n%2==1 && k==(n+1)/2-1 && (q==1 || q==2)){ continue; } if(s[k]=='2' || s[k]-48==q/2){ if(s[n-1-k]=='2' || s[n-1-k]-48==q%2){ for(long long r=0;r<4;r++){ long long sp=abs(q/2-r/2)+abs(q%2-r%2); if(n%2==0 && k==(n+1)/2-1 && (q==1 || q==2)){ sp++; } if(p<sp){ continue; } if(q==1){ dp[k][p][q][1]+=dp[k-1][p-sp][r][0]+dp[k-1][p-sp][r][1]; }else if(q==2){ dp[k][p][q][1]+=dp[k-1][p-sp][r][1]; }else{ dp[k][p][q][0]+=dp[k-1][p-sp][r][0]; dp[k][p][q][1]+=dp[k-1][p-sp][r][1]; } } } } } } } for(long long k=0;k<=l;k++){ long long a2=0; for(long long p=0;p<8;p++){ a2+=dp[(n+1)/2-1][k][p/2][p%2]; } all+=a2; } if(i>all){ i-=all;cout<<'X';s[v]='1'; }else{ cout<<'I'; } } } }
- 1
信息
- ID
- 2819
- 时间
- 1000ms
- 内存
- 32MiB
- 难度
- 10
- 标签
- 递交数
- 3
- 已通过
- 3
- 上传者