代码+注释
1 //我感觉这道题最扯的就是我因为输入而TLE了半天,懵逼死了,想破脑袋也没想到因为输入TLE了半天 2 //题意:求区间内数字满足“奇数各数出现偶数次,偶数各数出现奇数次”的数字的个数。 3 //题解: 4 //dp[x][y]表示长度为x的时候0~9各出现的状态情况,因为可能有未出现的情况,如果这个y用二进制 5 //保存的话那么未出现的偶数可能会因为0而出现误判,所以应该多一个状态,就用三进制。0表示未出现, 6 //1表示出现了奇数次,2表示出现了偶数次。 7 //就是一道状压+数位dp,和XHXJ's LIS HDU - 4352 很相似 8 //XHXJ's LIS HDU - 4352(这个是状压成二进制+dp):https://www.cnblogs.com/kongbursi-2292702937/p/11934243.html 9 10 #include<stdio.h> 11 #include<string.h> 12 #include<algorithm> 13 #include<iostream> 14 using namespace std; 15 const int maxn=20; 16 const int N=1<<10; 17 typedef long long ll; 18 ll v[maxn],dp[maxn][60000],w[15]; 19 //ll mul(ll x, ll y) { 20 // ll ret = 1; 21 // while(y) { 22 // if(y & 1) ret *= x; 23 // x *= x; 24 // y >>= 1; 25 // } 26 // return ret; 27 //} 28 //ll update(ll i,ll s) { 29 // ll ts = s, ti = i; 30 // while(ti--) ts /= 3; 31 // ll bit = ts % 3; 32 // if(bit < 2) return s + mul(3, i); 33 // return s - mul(3, i); 34 //} 35 ll update(ll x,ll y) //更新我们压缩的状态 36 { 37 ll ans[maxn],len=0; 38 memset(ans,0,sizeof(ans)); 39 while(y) 40 { 41 ans[len]=y%3; 42 len++; 43 y/=3; 44 } 45 if(ans[x]==0) 46 { 47 ans[x]=1; 48 } 49 else if(ans[x]==1) 50 ans[x]=2; 51 else ans[x]=1; 52 len=max(x+1,len); 53 54 y=0; 55 x=1; 56 for(ll i=0; i<len; ++i) 57 { 58 y+=ans[i]*x; 59 x*=3; 60 } 61 return y; 62 } 63 bool get_num(ll x) 64 { 65 ll ans[maxn],len=0; 66 memset(ans,0,sizeof(ans)); 67 while(x) 68 { 69 ans[len]=x%3; 70 len++; 71 x/=3; 72 } 73 bool flag=0; 74 for(ll i=0; i<len; ++i) 75 { 76 if(i==0 || i%2==0) 77 { 78 if(ans[i]!=0 && ans[i]!=1) 79 { 80 flag=1; 81 break; 82 } 83 84 } 85 else 86 { 87 if(ans[i]!=0 && ans[i]!=2) 88 { 89 flag=1; 90 break; 91 } 92 93 } 94 } 95 return flag; 96 } 97 ll dfs(ll pos,ll sta,bool limit,bool lead) 98 { 99 if(pos==-1) 100 { 101 if(!get_num(sta)) 102 return 1; 103 else return 0; 104 } 105 if(!limit && dp[pos][sta]!=-1) return dp[pos][sta]; 106 ll up=limit?v[pos]:9; 107 ll tmp=0; 108 for(ll i=0; i<=up; ++i) 109 { 110 if(lead && i==0) 111 { 112 tmp+=dfs(pos-1,0,limit && i==v[pos],1); 113 114 } 115 else 116 { 117 118 tmp+=dfs(pos-1,update(i,sta),limit && i==v[pos],0); 119 120 } 121 } 122 if(!limit) dp[pos][sta]=tmp; 123 return tmp; 124 } 125 ll solve(ll ans) 126 { 127 ll pos=0; 128 while(ans) 129 { 130 v[pos++]=ans%10; 131 ans/=10; 132 } 133 return dfs(pos-1,0,true,1); 134 } 135 int main() 136 { 137 int t; 138 ll l,r; 139 cin>>t; 140 memset(dp,-1,sizeof(dp)); 141 while(t--) 142 { 143 cin >> l >> r; 144 cout << solve(r) - solve(l-1) << endl; 145 } 146 return 0; 147 }