#3762. 有趣的数(number)

题意

内存限制:256 MiB
时间限制:2000 ms
这些天 nodgd 在研究一类有趣的数。定义函数 f ( n ) f(n) f(n) 表示 n n n 在十进制表示下的数字之和。如果一个正整数 n n n 满足 f ( n ) ∣ n f(n) \vert n f(n)n ,则 nodgd 认为 n n n 是有趣的。
例如: 3 3 3 7 7 7 12 12 12 84 84 84 111 111 111,这些数都是有趣的。显然有趣的数很多,于是 nodgd 想知道不超过 N N N 的所有正整数中有多少个是有趣的。
1 ≤ N ≤ 1 0 18 1 \leq N \leq 10^{18} 1N1018

题解

不会数位 d p dp dp 快乐 10 10 10
f i , j , k f_{i,j,k} fi,j,k 表示前 i i i 位,和为 j j j ,余数为 k k k 的个数
考虑主动转移即可
这个 f f f 值计算的是 &lt; n &lt;n <n 的答案
所以当前 i i i 位和 n n n 相等时,第 i + 1 i+1 i+1 位只能为 [ 0 , a i ) [0,a_i) [0,ai)
不然可以填 [ 0 , 9 ] [0,9] [0,9]
分讨即可
记得 f f 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;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值