题意:求给定区间,一个数的数位上每个奇数出现偶数次,每个偶数出现奇数次,这样数的个数
分析:先考虑状态,但总是想不全,所以要把状态压缩一下,用三进制,0 该数不放 1 放了奇数次 2放了偶数次
dp[i][j] 长度为i 状态是j的数字个数,需要前导0判断,前导0不能计入偶数出现的次数。
#include <map> #include <set> #include <list> #include <cmath> #include <queue> #include <stack> #include <cstdio> #include <vector> #include <string> #include <cctype> #include <complex> #include <cassert> #include <utility> #include <cstring> #include <cstdlib> #include <iostream> #include <algorithm> using namespace std; typedef pair<int,int> PII; typedef long long ll; #define lson l,m,rt<<1 #define pi acos(-1.0) #define rson m+1,r,rt<<11 #define All 1,N,1 #define read freopen("in.txt", "r", stdin) const ll INFll = 0x3f3f3f3f3f3f3f3fLL; const int INF= 0x7ffffff; const int mod = 1000000007; ll dp[25][100000],a,b; int bit[25],cas[15];
//化三进制 void get(int x) {for(int i=0; i<10; ++i){cas[i]=x%3;x/=3;} }
//状态改变 int change(int x,int b) {get(x);if(cas[b]==0)cas[b]=1;else if(cas[b]==1)cas[b]=2;else cas[b]=1;int s=0,tmp=1;for(int i=0; i<10; ++i){s+=cas[i]*tmp;tmp*=3;}return s; }
//判断符合条件 int judge(int s) {get(s);for(int i=0; i<10; ++i){if(i%2&&cas[i]==1)return 0;if(i%2==0&&cas[i]==2)return 0;}return 1; } ll dfs(int i,int j,int f,int e) {if(i==0)return judge(j);if(!e&&dp[i][j]!=-1)return dp[i][j];int u=e?bit[i]:9;ll num=0;for(int v=0; v<=u; ++v){if(f&&v==0)num+=dfs(i-1,0,1,e&&(v==u));else{num+=dfs(i-1,change(j,v),0,e&&(v==u));}}if(!e)dp[i][j]=num;return num; } ll solve(ll x) {int len=0;while(x){bit[++len]=x%10;x/=10;}return dfs(len,0,1,1); } int main() {int t;scanf("%d",&t);memset(dp,-1,sizeof(dp));while(t--){scanf("%I64d%I64d",&a,&b);printf("%I64d\n",solve(b)-solve(a-1));}return 0; }