题目描述
作为ACM史上年度重量级人物,bin巨目前已经掌握了史上最NB的数,群巨快来仰慕!!我们定义这样一个数,它里面的每一个数字都是成双成对出现 的,but,如果这个数里面存在0那么这也是NB的数,比如11,122122,12035,当然,需要剔除那些首位是0的数。我们的目标就是计算一个区 间内bin巨有多少NB数!
输入
输入第一行包含一个整数T,表示接下来有T组数据。
下面T行,每行包含两个数l和r,表示这个区间。
数据范围:0<=l<=r<=10^18
输出
输出T行,每行一个数字表示这个区间内的NB数!
样例输入
3 1 5 11 13 10 23
样例输出
0 1 4
小新巨巨出的一道数位DP:用二进制表示0~9每个数字出现的次数的奇偶。
0:表示出现偶数次,1:表示出现奇数次。
#include<cstdio> #include<cstring> #include<algorithm> #include<vector> #include<string> #include<iostream> #include<queue> #include<cmath> #include<map> #include<stack> #include<bitset> using namespace std; #define REPF( i , a , b ) for ( int i = a ; i <= b ; ++ i ) #define REP( i , n ) for ( int i = 0 ; i < n ; ++ i ) #define CLEAR( a , x ) memset ( a , x , sizeof a ) typedef long long LL; typedef pair<int,int>pil; const int INF = 0x3f3f3f3f; const int maxn=1e5+100; LL l,r; int t; int num[30]; LL dp[20][1800][2]; int ok(int x) { if(x&1) return 1; for(int i=1;i<=9;i++) if(x&(1<<i)) return 0; return 1; } LL dfs(int pos,int s,int first,int flag) { if(pos==0) return first&&ok(s); if(!flag&&dp[pos][s][first]!=-1) return dp[pos][s][first]; LL ans=0; int ed=flag?num[pos]:9; for(int i=0;i<=ed;i++) { int f=first; if(!first&&i) f=1; if(f&&i==0) ans+=dfs(pos-1,s|1,f,flag&&i==ed); else if(!f&&!i) ans+=dfs(pos-1,s,f,flag&&i==ed); else ans+=dfs(pos-1,s^(1<<i),f,flag&&i==ed); } if(!flag) dp[pos][s][first]=ans; return ans; } LL solve(LL x) { if(x==0) return 1; int pos=0; while(x) { num[++pos]=x%10; x/=10; } return dfs(pos,0,0,1)+1; } int main() { CLEAR(dp,-1); scanf("%d",&t); while(t--) { scanf("%lld%lld",&l,&r); LL ans=solve(r)-solve(l-1); printf("%lld\n",ans); } return 0; }
时间: 2024-10-18 09:04:08