题意:一个数,如果满足奇数的数字出现偶数次,偶数的数字出现奇数次,
就是符合的数,注比如: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 }