管道取珠
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了管道取珠相关的知识,希望对你有一定的参考价值。
平方转化为两个人取到相同的方案,这是一个小trick
为什么这样是对的?
假设第一个人取方案是$x$,第二个人取方案是$y$,根据乘法原理就是$x*y$,又因为两个人取得方案数相同所以$x==y$,即$x^2$
所以设f[a][b][c][d]表示第一个人从第一个管道取a,第一个人从管道取b,第二个人从管道取c,第二个人从管道取d
优化一下可以去掉一维
#include<bits/stdc++.h> using namespace std; #define ll long long #define A 551 #define mod 1024523 ll f[2][A][A]; //方案数相同那么取得个数必然相同,i表示总个数,j表示甲在a取了多少,q表示乙在a取了多少 ll n,m; char up[510],down[510]; int main(){ // freopen("da.in","r",stdin); // freopen("ans.sol","w",stdout); scanf("%lld%lld",&n,&m); scanf("%s",up+1); scanf("%s",down+1); reverse(up+1,up+n+1); reverse(down+1,down+m+1); memset(f,0,sizeof(f)); f[0][0][0]=1; for(ll i=1;i<=n+m;i++){ memset(f[i&1],0,sizeof(f[i&1])); for(ll a1=0;a1<=min(n,i);a1++){ for(ll a2=0;a2<=min(n,i);a2++){ ll b1=i-a1,b2=i-a2; if(b1<0||b2<0) continue ; //两个都从b取 // if(b1<=0||b2<=0) continue ; // printf("b1=%lld b2=%lld ",b1,b2); if(down[b1]==down[b2]) (f[i&1][a1][a2]+=f[(i-1)&1][a1][a2])%=mod; //一个从up一个从down if(a1) if(up[a1]==down[b2]) (f[i&1][a1][a2]+=f[(i-1)&1][a1-1][a2])%=mod; if(a2) if(up[a2]==down[b1]) (f[i&1][a1][a2]+=f[(i-1)&1][a1][a2-1])%=mod; //都从上 if(a1&&a2) if(up[a1]==up[a2]) (f[i&1][a1][a2]+=f[(i-1)&1][a1-1][a2-1])%=mod; // printf("f[%lld][%lld][%lld]=%lld a=%lld b=%lld c=%lld d=%lld e=%lld ",i,a1,a2,f[i&1][a1][a2],f[(i-1)&1][a1][a2],f[(i-1)&1][a1-1][a2],f[(i-1)&1][a1][a2-1],f[(i-1)&1][a1-1][a2-1],f[0][0][0]); } } }ll ans=0; printf("%lld",f[(n+m)&1][n][n]); }
不会做$noip-$难度题了
早就想写但代码在bzoj
以上是关于管道取珠的主要内容,如果未能解决你的问题,请参考以下文章