[NOI2009] 管道取珠
题面很晦涩
直接关键部分:
最后我们所要求的 ∑ai2 其实也就是我们得出相同的输出的方案。
这样子我们就有了基本的想法:dp
但是很显然我们需要知道我们1是如何从上下两个管子里取出的,状压肯定是不行的,所以我们去推一下转移的式子,看可不可优化空间
最好想到的就是我们—— dp [i][j] [k][len]
记录下来两个人从上/下分别(其实上下可以推出来)取得球数
接下来就是喵的地方了
我们需要的状态只有 i+j==k+l 的方案
所以我们直接压吊一位
dp[l][i][j]
表示取 l 个,两个人分别从上下取 i,j 个
然后滚动数组滚掉l,这样空间就可接受了:2*500*500;
#include<bits/stdc++.h> using namespace std; const int N=504; const int mod=1024523; int n,m; char s1[N],s2[N]; int dp[5][N][N]; int main() { ios::sync_with_stdio(false); cin>>n>>m; cin>>s1+1>>s2+1; dp[0][0][0]=1; for(int i=0;i<=n;i++) { int x=i&1; int pre=x^1; memset(dp[pre],0,sizeof(dp[pre])); for(int j=0;j<=m;j++) { for(int k=0;k<=i+j;k++) { int len=i+j-k; if(s1[i+1]==s1[k+1]) (dp[x^1][j][k+1]+=dp[x][j][k])%=mod; if(s1[i+1]==s2[len+1]) (dp[x^1][j][k]+=dp[x][j][k])%=mod; if(s2[j+1]==s1[k+1]) (dp[x][j+1][k+1]+=dp[x][j][k])%=mod; if(s2[j+1]==s2[len+1]) (dp[x][j+1][k]+=dp[x][j][k])%=mod; } } } cout<<dp[n&1][m][n]; return 0; }