数位dp
f[i][st][w1][w2]表示到第i位,这一位a,b,c,d的数是否分别要小于ABCD的状态st,w1表示前一位a+c-b-d为几,w2表示a+d-b-c为几
由于前一位差大于等于2后,后面能始终确保a+c>b+d,所以w1, w2状态只有-1,0,1,2四种
注意这时如果按十进制诸位考虑,复杂度为18*9^4*16*4*4会超时
而逐二进制位复杂度为61*2^4*16*4*4,如此可过
1 #include<bits/stdc++.h> 2 3 using namespace std; 4 typedef long long ll; 5 const int mo=1e9+7; 6 int f[62][16][4][4],g[4][62]; 7 ll a,b,c,d; 8 9 int dfs(int i,int st,int w1,int w2) 10 { 11 if (i==-1) 12 { 13 if (w1>=2&&w2>=1) return 1; 14 else return 0; 15 } 16 if (f[i][st][w1][w2]>-1) return f[i][st][w1][w2]; 17 int s=0,r[4]; 18 for (int j=0; j<4; j++) r[j]=((st>>j)&1)?1:g[j][i]; 19 for (int a0=0; a0<=r[0]; a0++) 20 for (int b0=0; b0<=r[1]; b0++) 21 for (int c0=0; c0<=r[2]; c0++) 22 for (int d0=0; d0<=r[3]; d0++) 23 { 24 int nw=st,q1,q2; 25 int l=a0+c0+(w1-1)*2-b0-d0; 26 if (l<-1) continue; else q1=(l>1)?2:l; 27 l=a0+d0+(w2-1)*2-b0-c0; 28 if (l<-1) continue; else q2=(l>1)?2:l; 29 if (a0<r[0]) nw|=1; 30 if (b0<r[1]) nw|=2; 31 if (c0<r[2]) nw|=4; 32 if (d0<r[3]) nw|=8; 33 s=(s+dfs(i-1,nw,q1+1,q2+1))%mo;; 34 } 35 36 f[i][st][w1][w2]=s; 37 return s; 38 } 39 40 void work(ll x,int w) 41 { 42 int t=0; 43 while (x) 44 { 45 g[w][t++]=x%2; 46 x/=2; 47 } 48 } 49 50 int main() 51 { 52 int cas; 53 scanf("%d",&cas); 54 while (cas--) 55 { 56 scanf("%lld%lld%lld%lld",&a,&b,&c,&d); 57 memset(g,0,sizeof(g)); 58 work(a,0); work(b,1); work(c,2); work(d,3); 59 memset(f,255,sizeof(f)); 60 printf("%d ",dfs(61,0,1,1)); 61 } 62 }