BZOJ 1566 【NOI2009】 管道取珠

题目链接:管道取珠

  这道题思路还是很巧妙的。

  一开始我看着那个平方不知所措……看了题解后发现,这种问题有一类巧妙的转化。我们可以看成两个人来玩这个游戏,那么答案就是第二个人的每个方案第一个人的所有方案中出现次数的和。

  于是(dp)就显而易见了。(f_{i,j,k})表示取了前(i)个,第一个人从上面拿了(j)个,第二个人从上面拿了(k)个的方案数。

  还有这道题一开始读入的串翻不翻转无所谓。反正答案不会变。

  大概以后碰到平方都能往这上面想想?

  下面贴代码:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#define File(s) freopen(s".in","r",stdin),freopen(s".out","w",stdout)
#define mod 1024523
#define N 510

using namespace std;
typedef long long llg;

int n,m,f[2][N][N];
char a[N],b[N];

int main(){
	File("a");
	scanf("%d %d",&n,&m);
	scanf("%s %s",a,b);
	int no=0,la; f[0][0][0]=1;
	for(int o=0,l,r,p,q;o<n+m;o++){
		la=no,no^=1; l=max(o-m,0),r=min(o,n);
		for(int i=l;i<=r;i++)
			for(int j=l;j<=r;j++){
				if(!f[la][i][j]) continue;
				p=o-i; q=o-j;
				if(a[i]==a[j]) (f[no][i+1][j+1]+=f[la][i][j])%=mod;
				if(a[i]==b[q]) (f[no][i+1][j]+=f[la][i][j])%=mod;
				if(b[p]==a[j]) (f[no][i][j+1]+=f[la][i][j])%=mod;
				if(b[p]==b[q]) (f[no][i][j]+=f[la][i][j])%=mod;
				f[la][i][j]=0;
			}
	}
	printf("%d",f[no][n][n]);
	return 0;
}
原文地址:https://www.cnblogs.com/lcf-2000/p/6528974.html