题意:一个数,如果满足奇数的数字出现偶数次,偶数的数字出现奇数次,
就是符合的数,注比如:12313 就满足,因为1 3出现了偶数次。2出现了奇数次
思路,对于这道题,就是状态压缩加dp;
对于一个数字来说,0~9每一位,都只有3种状态量,要么从未出现,要么出现次数为奇
要么为偶,所以可以用3进制来表示,通过3进制表示出其状态,然后到pos-1的时候
判断0~9的各个状态是否符合条件即可
1 #include<cstdio> 2 #include<string.h> 3 using namespace std; 4 typedef long long ll; 5 ll dp[20][60000]; 6 ll a[20]; 7 int check(int s) 8 { 9 for(int i=0;i<=9;++i){ 10 int k=s%3; 11 s/=3; 12 if(k==0) continue; 13 else if((i&1)&&k==1) return 0; //若为奇数,如果出现次数也为奇,则退出; 14 else if(!(i&1)&&k==2) return 0; //若为偶数,。。。。。。。。。。。。。。 15 } 16 return 1; 17 } 18 //三进制代码; 19 int change(int d,int s) 20 { 21 int temp[12]; 22 for(int i=0;i<=9;i++){ 23 temp[i]=s%3; 24 s/=3; 25 } 26 s=0; 27 if(temp[d]==0) temp[d]=1; //表示其状态的代码 28 else temp[d]=3-temp[d]; //表示其状态的代码 29 for(int i=9;i>=0;i--) 30 s=s*3+temp[i]; 31 return s; 32 } 33 34 ll dfs(ll pos,ll sum,bool flag,bool limit) 35 { 36 //flag是判断前导0用的 37 if(pos==-1) return check(sum); 38 if(!limit&&dp[pos][sum]!=-1) return dp[pos][sum]; 39 int up=limit? a[pos]:9; 40 ll ans=0; 41 for(int i=0;i<=up;i++) 42 //如果之前一直都是0,i==0,则sum的值依旧等于0 43 ans+=dfs(pos-1,(flag==0&&i==0)? 0:change(i,sum),flag||i>0,limit&&i==a[pos]); 44 if(!limit) dp[pos][sum]=ans; //如果i已经大于0,则再也没有前导0这一说法 45 return ans; 46 } 47 ll solve(ll x) 48 { 49 int pos=0; 50 while(x){ 51 a[pos++]=x%10; 52 x/=10; 53 } 54 return dfs(pos-1,0,0,true); 55 } 56 int main() 57 { 58 int T; 59 scanf("%d",&T); 60 memset(dp,-1,sizeof(dp)); 61 while(T--){ 62 ll l,r; 63 scanf("%lld%lld",&l,&r); 64 printf("%lld\n",solve(r)-solve(l-1)); 65 } 66 return 0; 67 }