P4127 [AHOI2009]同类分布

P4127 [AHOI2009]同类分布

题目描述

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


Solution

发现题目有两个变量

  1. 数位之和
  2. 原数

于是必须想办法设计一个只有一种变量的数位dp,
发现唯有固定数位之和才可以在DFS中将取模作为状态方便地转移

记搜元素:

  1. 当前数位
  2. 数位之和
  3. 原数的模值

Code

#include<bits/stdc++.h>
#define reg register
#define pb push_back

typedef long long ll;

std::vector <int> Bt;
ll dp[19][205][205];
int mod;

ll DFS(int k, int flag, int sum_1, int sum_m){
        if(sum_1 > mod) return 0;
        if(k == -1){
                if(!sum_m && sum_1==mod) return 1;
                return 0;
        }
        if(!flag && ~dp[k][sum_1][sum_m]) return dp[k][sum_1][sum_m];
        int end = flag?Bt[k]:9;
        ll tmp = 0;
        for(reg int i = 0; i <= end; i ++)
                tmp += DFS(k-1, flag&&i==end, sum_1+i, (sum_m*10 + i)%mod);
        if(!flag) dp[k][sum_1][sum_m] = tmp;
        return tmp;
}

ll Work(ll x){
        Bt.clear();
        while(x) Bt.pb(x%10), x /= 10;
        ll res = 0;
        int size = Bt.size();
        for(mod = 1; mod <= 9*size; mod ++){ 
                memset(dp, -1, sizeof dp);
                res += DFS(size - 1, 1, 0, 0);
        }
        return res;
}

int main(){
        ll A, B;
        scanf("%lld%lld", &A, &B);
        printf("%lld", Work(B) - Work(A-1));
        return 0;
}

原文地址:https://www.cnblogs.com/zbr162/p/11822686.html