找出区间[A, B]内所有数字的奇数字位出现次数为偶数,偶数字位出现次数为计数的数的个数。(数位DP)

Posted shuaihui

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了找出区间[A, B]内所有数字的奇数字位出现次数为偶数,偶数字位出现次数为计数的数的个数。(数位DP)相关的知识,希望对你有一定的参考价值。

题目:找出区间[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
", solve(B)-solve(A-1));
    }
    return 0;
}
View Code

 





以上是关于找出区间[A, B]内所有数字的奇数字位出现次数为偶数,偶数字位出现次数为计数的数的个数。(数位DP)的主要内容,如果未能解决你的问题,请参考以下文章

2021-12-19:找到所有数组中消失的数字。 给你一个含 n 个整数的数组 nums ,其中 nums[i] 在区间 [1, n] 内。请你找出所有在 [1, n] 范围内但没有出现在 nums(

text 统计一个区间内某个数字的出现次数

1042 数字0-9的数量(非数位dp解法)

剑指56-2 数组中数字出现的次数

求一个整数区间(从1到n)内1出现的次数

数字0-9的数量