#3762. 有趣的数(number)

题意
内存限制:256 MiB
时间限制:2000 ms
这些天 `nodgd` 在研究一类有趣的数。定义函数 $ f(n) $ 表示 $ n $ 在十进制表示下的数字之和。如果一个正整数 $ n $ 满足 $ f(n) \vert n $ ,则 `nodgd` 认为 $ n $ 是有趣的。
例如:$ 3 $,$ 7 $,$ 12 $,$ 84 $,$ 111 $,这些数都是有趣的。显然有趣的数很多,于是 `nodgd` 想知道不超过 $ N $ 的所有正整数中有多少个是有趣的。
$ 1 \leq N \leq 10^{18} $
题解
不会数位 $dp$ 快乐 $10$ 分
设 $f_{i,j,k}$ 表示前 $i$ 位,和为 $j$ ,余数为 $k$ 的个数
考虑主动转移即可
这个 $f$ 值计算的是 $<n$ 的答案
所以当前 $i$ 位和 $n$ 相等时,第 $i+1$ 位只能为 $[0,a_i)$
不然可以填 $[0,9]$
分讨即可
记得 $f$ 要清零

#include <bits/stdc++.h>
#define LL long long
LL n,f[20][170][170],ans;
int a[20],t,s[20];
int main(){
    scanf("%lld",&n);LL m=n;
    while(n) a[++t]=n%10,n/=10;
    for (int i=1;i+i<=t;i++) std::swap(a[i],a[t-i+1]);
    for (int i=1;i<=t;i++) s[i]=s[i-1]+a[i];
    for (int g=1;g<=9*t;g++){
        for (int i=1;i<=t;i++)
            for (int j=0;j<=9*i && j<=g;j++)
                for (int k=0;k<g;k++) f[i][j][k]=0;
        for (int d=0,i=0;i<t;i++,d=(10*d+a[i])%g){
            for (int j=0;j<=9*i && j<=g;j++)
                for (int k=0;k<g;k++)
                    for (int x=0;x<=9 && j+x<=g;x++)
                        f[i+1][j+x][(10*k+x)%g]+=f[i][j][k];
            for (int x=0;x<a[i+1] && s[i]+x<=g;x++)
                f[i+1][s[i]+x][(10*d+x)%g]++;
        }
        ans+=f[t][g][0];
    }
    return printf("%lld\n",ans+(m%s[t]==0)),0;
}

 

posted @ 2019-03-23 17:05  xjqxjq  阅读(301)  评论(0编辑  收藏  举报