[bzoj1566][NOI2009]管道取珠
来自FallDream的博客,未经允许,请勿转载,谢谢。
n<=500
神题......
发现这个平方可以看作两个序列相同的对数 然后就可以表示状态了。
f[i][j][k]表示两个序列各选了i个,第1个序列在第一行选了j个,第二个序列在第二行选了k个,他们相同的方案数
转移比较简单,枚举两个序列各填哪一位即可。
复杂度n^3
#include<iostream> #include<cstdio> #include<cstring> #define MN 500 #define mod 1024523 using namespace std; inline int read() { int x = 0 , f = 1; char ch = getchar(); while(ch < '0' || ch > '9'){ if(ch == '-') f = -1; ch = getchar();} while(ch >= '0' && ch <= '9'){x = x * 10 + ch - '0';ch = getchar();} return x * f; } int f[2][505][505],n,m; char A[MN+5],B[MN+5]; inline void R(int&x,int y){x+=y;x>=mod?x-=mod:0;} int main() { n=read();m=read(); scanf("%s",A+1);scanf("%s",B+1); f[0][0][0]=1; for(int i=0,now=1,pre=0;i<n+m;++i) { for(int j=0;j<=min(i,n);++j) for(int k=0;k<=min(i,n);++k) { int J=i-j,K=i-k; if(j<n&&k<n&&A[j+1]==A[k+1]) R(f[now][j+1][k+1],f[pre][j][k]); if(j<n&&K<m&&A[j+1]==B[K+1]) R(f[now][j+1][k],f[pre][j][k]); if(J<m&&k<n&&B[J+1]==A[k+1]) R(f[now][j][k+1],f[pre][j][k]); if(J<m&&K<m&&B[J+1]==B[K+1]) R(f[now][j][k],f[pre][j][k]); } swap(now,pre); memset(f[now],0,sizeof(f[now])); } printf("%d\n",f[(n+m)&1][n][n]); return 0; }
FallDream代表秋之国向您问好!
欢迎您来我的博客www.cnblogs.com/FallDream
【推荐】100%开源!大型工业跨平台软件C++源码提供,建模,组态!
【推荐】园子的不务正业:向创业开发者推荐「楼盘」- 杭州云谷中心
【推荐】2025 HarmonyOS 鸿蒙创新赛正式启动,百万大奖等你挑战
【推荐】天翼云爆款云主机2核2G限时秒杀,28.8元/年起!立即抢购
· Ribbon LoadBalancer: 开源的客户端式负载均衡框架
· EF Core:再谈普通实体关系与 Owned 关系的区别
· C++20新增属性[[no_unique_address]]详解
· 线上频繁FullGC?竟是Log4j2的这个“特性”坑了我
· 聊一聊 .NET 中的 CancellationTokenSource
· 刚刚 Java 25 炸裂发布!让 Java 再次伟大
· 一款基于 .NET 开源美观、功能丰富的串口调试工具
· .NET 10 是微软 AI 战略的技术承重墙
· Runtime Async - 步入高性能异步时代
· AI 开发者工具 TOP 榜:9 大分类 + 20种工具