P4127 [AHOI2009]同类分布

链接:https://www.luogu.org/problemnew/show/P4127

题目描述

给出两个数 a,ba,b ,求出 [a,b][a,b] 中各位数字之和能整除原数的数的个数。

输入输出格式

输入格式:

一行,两个整数 aa 和 bb

输出格式:

一个整数,表示答案

输入输出样例

输入样例#1: 复制
10 19
输出样例#1: 复制
3

说明

对于所有的数据, 1 ≤ a ≤ b ≤ 10^18

题解:数位dp, 但有一个问题,我们不知道各个数位数字之和;18*9是很小的,我们枚举一个一个试就可以了,这次学会了不用存顶上界,特判,情况少

#include<bits/stdc++.h>
using namespace std;
#define ll long long
int digit[20];
ll dp[20][200][2][200];
ll dfs(int dep, int yu, int f, int t, int now, int sum){
    if(!dep) return !yu && sum == now;
    if(sum > now || sum + dep * 9 < now)return 0;
    if(dp[dep][yu][f][sum] != -1)return dp[dep][yu][f][sum];
    int i = f ? digit[dep] : 9;
    ll tmp = 0;
    for(; i >= 0; i--) {
        tmp += dfs(dep-1, (yu*10 + i) % now, f&(i == digit[dep]), i, now, sum+i);
        
    }
    return dp[dep][yu][f][sum] = tmp;
}

ll get(ll a){
    
    int cnt = 0;
    int now = 0;
    while(a){
        digit[++cnt] = a % 10;
        a /= 10;
        now += digit[cnt];
    }
    ll ans = 0;
    for(int i = 1; i <= 9*cnt; i++){
        memset(dp, -1, sizeof(dp));
        ans += dfs(cnt, 0, 1, 0, i, 0);
    }    
    return ans;
}
// 1000000 7000000000000

int main(){
    int kk = clock();
    ll L, R;
    cin>>L>>R;
    ll ans1 = get(L-1);
    ll ans2 = get(R);
    cout<<ans2-ans1<<endl;
    int cc = clock();
    //cout<<cc-kk;
}
View Code
原文地址:https://www.cnblogs.com/EdSheeran/p/9397195.html