数位dp的思想就在于递归,记录当前的某一个唯一状态,依次递归下去,要注意唯一。

数位dp常设的状态有当前位置,上一数字,是否具有前导零,是否有限制。

1.CodeForces 55DBeautiful numbers

题目大意:一个数是幸运数当且仅当这个数能整除所有位数,求[a,b]有多少幸运数

10以内的数的最小公倍数是2520,状态为当前位置,模2520的值,出现了哪些数字(状压,1,0删去)

#include<iostream>
#include<stdio.h>
#include<string.h>
using namespace std;
const int maxa = 20;
const int mod = 2520;
long long  dp[maxa][1<<8][mod];
#define LL long long
//当前位置,限制,有哪些数,模
int num[maxa];
LL dfs(int pos, int limit, int val, int numb){
    if(pos == 0){
        for(int i = 2; i < 10; i++){
            if((1<<(i-2)) & val){
                if(numb % i) return 0;
            }
        }return 1;
    }
    if(!limit && dp[pos][val][numb] != -1) return dp[pos][val][numb];
    int nn = limit?num[pos]:9;
    LL res = 0;
    for(int i = 0; i <= nn; i++){
        res += dfs(pos-1, limit & (i ==nn), i<2?val:val|(1<<(i-2)), (numb*10+i)%mod);
    }
    if(!limit) dp[pos][val][numb] = res;
    return res;
}
LL ANS(LL n){
    int leng = 0;
    while(n){
        num[++leng] = n %10;
        n /= 10;
    }
    return dfs(leng, 1, 0, 0);
}
int main(){
    int t;
    LL a, b;
    memset(dp, -1, sizeof(dp));
    scanf("%d", &t);
    while(t--){
        cin>>a>>b;
        if(a > b)swap(a, b);
        cout<<ANS(b) - ANS(a-1)<<endl;
    }
}
View Code

相关文章:

  • 2022-01-02
猜你喜欢
  • 2022-01-16
  • 2021-08-07
  • 2021-09-02
  • 2022-01-15
  • 2021-07-18
相关资源
相似解决方案