题目:找出区间[A, B]内所有数字的奇数字位出现次数为偶数,偶数字位出现次数为计数的数的个数。
分析:这道题的状态同样不好取,因为要求每一个奇数的个数都要为偶数,每一个偶数的位数都要为奇数,又因为只有10个数(0~9),又因为没个数只有3种状态,分别是没有(0),奇数个(1),偶数个(2),这样我们就利用3进制进行压缩就可以了,3的10次方不超过60000,因此直接开60000即可,这样dp[i][j]的i表示当前处理到了第i为,j表示当前(0~9)对应的状态
#include <cmath> #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> using namespace std; const int maxn = 25; typedef long long LL; LL dp[maxn][60000],bit[maxn]; int judge(int state){ //计算是否满足题意,奇数为偶,偶数为奇 for(int i = 0; i <= 9; ++i, state/=3) { if((i&1)==1&&state%3==1) { return 0; } if((i&1)==0&&state%3==2) { return 0; } } return 1; } int change(int state,int i){ int temp = state; int j = i; while(j--){///取到当前位 temp /= 3; } int x = temp%3; if(x == 0) state += (int)pow(3.0, i); else if(x == 1) state += (int)pow(3.0, i); else state -= (int)pow(3.0, i); return state; } LL dfs(int pos,int state,int limit){ if(pos < 1) return judge(state); LL &ans = dp[pos][state]; if(!limit && ans != -1) return ans; LL ret = 0; int len = limit?bit[pos]:9; for(int i = 0; i <= len; i++) ret += dfs(pos-1, state==0&&i==0?0:change(state, i), limit&&i==len); if(!limit) ans = ret; return ret; } LL solve(LL n){ int len = 0; while(n){ bit[++len] = n%10; n /= 10; } return dfs(len, 0, 1); } int main() { int T; scanf("%d", &T); LL A,B; memset(dp, -1, sizeof(dp)); while(T--){ scanf("%lld%lld", &A, &B); printf("%lld\n", solve(B)-solve(A-1)); } return 0; }
原文地址:https://www.cnblogs.com/shuaihui520/p/9938710.html
时间: 2024-10-13 05:26:12