bzoj4513: [Sdoi2016]储能表
看到带sigema的不要想着就是数论,也可以是数位DP啊
讨论的时候多利用for循环,不然讨论到自闭
#include<cstdio> #include<iostream> #include<cstring> #include<cstdlib> #include<algorithm> #include<cmath> using namespace std; typedef long long LL; LL n,m,K,mod; int len[3],a[3][70],maxbit; void divi(LL x,int w) { len[w]=0; memset(a[w],0,sizeof(a[w])); while(x!=0) { a[w][++len[w]]=x%2; x/=2; } } LL Bin[70]; LL f[70][2][2][2],g[70][2][2][2]; void dfs(int k,int u,int v,int w) { if(f[k][u][v][w]!=-1)return ; if(k==0){f[k][u][v][w]=0,g[k][u][v][w]=1;return ;} int bu=((u==0)||(a[0][k]==1)); int bv=((v==0)||(a[1][k]==1)); int bw=((w==1)&&(a[2][k]==1)); f[k][u][v][w]=0; for(int i=0;i<=bu;i++) for(int j=0;j<=bv;j++) if((i^j)>=bw) { int tu=((u==1)&&(i==bu)); int tv=((v==1)&&(j==bv)); int tw=((w==1)&&((i^j)==bw)); dfs(k-1,tu,tv,tw); f[k][u][v][w]=(f[k][u][v][w]+f[k-1][tu][tv][tw]+Bin[k]*(i^j)*g[k-1][tu][tv][tw])%mod; g[k][u][v][w]=(g[k][u][v][w]+g[k-1][tu][tv][tw])%mod; } } int main() { // freopen("a.in","r",stdin); // freopen("a.out","w",stdout); int T; scanf("%d",&T); while(T--) { scanf("%lld%lld%lld%lld",&n,&m,&K,&mod);n--,m--; divi(n,0),divi(m,1),divi(K,2); if(len[2]>len[0]&&len[2]>len[1]){puts("0");continue;} maxbit=max(len[0],len[1]); Bin[1]=1;for(int i=2;i<=maxbit;i++)Bin[i]=Bin[i-1]*2%mod; memset(f,-1,sizeof(f)); memset(g,0,sizeof(g)); dfs(maxbit,1,1,1); printf("%lld\n",((f[maxbit][1][1][1]-g[maxbit][1][1][1]*(K%mod))%mod+mod)%mod); } return 0; }
pain and happy in the cruel world.