標籤:
我真TM是個sb!!!
f[i][0/1][0/1][0/1]表示考慮到第i位前i位是否卡n的上界,是否卡m的上界,是否卡k的下界的數對的個數
g[i][0/1][0/1][0/1]表示考慮到第i位前i位是否卡n的上界,是否卡m的上界,是否卡k的下界的數對的和
直接dp
#include<cstdio>#include<cstring>#include<cstdlib>#include<cmath>#include<iostream>#include<algorithm>using namespace std;long long f[110][2][2][2],g[110][2][2][2],bin[64];long long n,m,mod,k;int T;int main(){scanf("%d",&T);while (T--){scanf("%lld%lld%lld%lld",&n,&m,&k,&mod);n--;m--;long long ans=0;bin[0]=1;for (int i=1;i<=63;i++) bin[i]=(long long)bin[i-1]*2ll%mod;memset(f,0,sizeof(f));memset(g,0,sizeof(g));f[0][1][1][1]=1;g[0][1][1][1]=0;for (int i=0;i<=63;i++) for (int a=0;a<2;a++) for (int b=0;b<2;b++) for (int c=0;c<2;c++) if (f[i][a][b][c]) { int p=((n&(1ll<<(63-i)))==0)?0:1; int q=((m&(1ll<<(63-i)))==0)?0:1; int t=((k&(1ll<<(63-i)))==0)?0:1; for (int x=0;x<2;x++) { if (a && x>p) continue; for (int y=0;y<2;y++) { if (b && y>q) continue; int z=x^y; if (c && z<t) continue; int A=(a && x==p)?1:0; int B=(b && y==q)?1:0; int C=(c && z==t)?1:0; f[i+1][A][B][C]=(f[i+1][A][B][C]+f[i][a][b][c])%mod; g[i+1][A][B][C]=(g[i+1][A][B][C]+g[i][a][b][c]+((z==0)?0:bin[63-i])*f[i][a][b][c]%mod)%mod; } } }k%=mod;for (int a=0;a<2;a++) for (int b=0;b<2;b++) for (int c=0;c<2;c++) ans=(ans+g[64][a][b][c]-k*f[64][a][b][c]%mod+mod)%mod;printf("%lld\n",ans);}return 0;}
【bzoj4513】[Sdoi2016]儲能表 數位dp