bzoj4513 储能表 数位dp

来源:互联网 发布:jsp 获取客户端mac 编辑:程序博客网 时间:2024/06/15 05:32
       令f[len][S1][S2][S3]表示前len位,i满足状态S1,j满足状态S2,i^j满足状态S3。S1=0表示i的前len位比n的前len位小,1表示不作要求;S2同理;S3=0表示i^j>=k,否则表示不作要求。

       然后就可以轻松转移辣~\(≧▽≦)/~。

AC代码如下:

#include<iostream>#include<cstdio>#include<cstring>#include<set>#include<algorithm>#include<cmath>#include<cstdlib>#define ll long long#define N 105using namespace std;ll n,m,k; int p,lenm,lenn,lenk,len,a[N],b[N],c[N],f[N][2][2][2],g[N][2][2][2],bin[N];void ad(int &x,int y){ x+=y; if (x>=p) x-=p; }int main(){int cas,i,x,y,z; scanf("%d",&cas);while (cas--){scanf("%lld%lld%lld%d",&m,&n,&k,&p);memset(a,0,sizeof(a)); memset(b,0,sizeof(b)); memset(c,0,sizeof(c));lenm=0; for (; m; m>>=1) a[++lenm]=m&1;lenn=0; for (; n; n>>=1) b[++lenn]=n&1;lenk=0; for (; k; k>>=1) c[++lenk]=k&1;len=max(max(lenm,lenn),lenk);bin[0]=1; for (i=1; i<=len; i++) bin[i]=(bin[i-1]<<1)%p;int i,j,k,l,x,y,z,u,v,tmp;memset(f,0,sizeof(f)); memset(g,0,sizeof(g));for (x=0; x<2; x++) for (y=0; y<2; y++) for (z=0; z<2; z++)for (u=0; u<((x)?2:a[1]); u++)for (v=0; v<((y)?2:b[1]); v++)if ((u^v)>=c[1] || z){ad(f[1][x][y][z],((u^v)-c[1]+p)%p);ad(g[1][x][y][z],1);}for (i=2; i<=len; i++)for (x=0; x<2; x++) for (y=0; y<2; y++) for (z=0; z<2; z++)for (u=0; u<=max(x,a[i]); u++)for (v=0; v<=max(y,b[i]); v++)if ((u^v)>=c[i] || z){j=x|(u<a[i]); k=y|(v<b[i]); l=z|((u^v)>c[i]);tmp=(ll)g[i-1][j][k][l]*((u^v)-c[i])*bin[i-1]%p;if (tmp<0) tmp+=p; ad(tmp,f[i-1][j][k][l]);ad(f[i][x][y][z],tmp);ad(g[i][x][y][z],g[i-1][j][k][l]);}printf("%d\n",f[len][0][0][0]);}return 0;}


by lych

2016.4.21

0 0
原创粉丝点击