有趣的数(number)

有趣的数(number)

题目描述

这些天 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 的所有正整数中有多少个是有趣的。

输入格式

输入只有一行,包含一个正整数 N N N。

输出格式

输出只有一行,包含一个整数,表示答案。

样例

样例输入 1

11

样例输出 1

10

【样例解释 1】
不超过 11 11 11 的所有正整数中,只有 11 11 11 不是有趣的。

样例输入 2

12345678

样例输出 2

1017860

数据范围与提示

对于 10% 10 \% 10% 的数据,N≤106 N \leq 10^6 N106;
对于 30% 30 \% 30% 的数据,N≤109 N \leq 10^9 N109;
对于 60% 60 \% 60% 的数据,N≤1012 N \leq 10^{12} N1012;
对于 100% 100 \% 100%的数据,1≤N≤1018 1 \leq N \leq 10^{18} 1N1018。


solution
10^18考虑数位dp
由于数位和不超过162,我们可以先枚举他。
记f[i][x][y][0/1]表示前i位,数位和x,前i位模完为y,是否顶满。
考场我有个变量没开ll,悲伤的故事
 1 #include<cstdio>
 2 #include<iostream>
 3 #include<cstdlib>
 4 #include<cstring>
 5 #include<algorithm>
 6 #include<cmath>
 7 #define ll long long
 8 using namespace std;
 9 ll n,f[19][180][180][2],p[20],ans;
10 int sum,tp,N[20];
11 ll dfs(int i,int x,int y,bool ful){
12     ll &S=f[i][x][y][ful];
13     if(S!=-1)return S;
14     S=0;
15     if(i==0){
16         if(x==sum&&y==0){
17             S++;
18         }
19         return S;
20     }
21     for(int t=0;t<10;t++){
22         if(ful&&t>N[i])break;
23         S+=dfs(i-1,x+t,(y+1LL*t*p[i])%sum,ful&(t==N[i]));
24     }
25     return S;
26 }
27 int main()
28 {
29     cin>>n;int Max=0;
30     p[1]=1;for(int i=2;i<=18;i++)p[i]=p[i-1]*10;
31     for(ll x=n;x;x=x/10)Max=Max+9,tp++,N[tp]=x%10;
32     for(sum=1;sum<=Max;sum++){
33         memset(f,-1,sizeof f);
34         dfs(tp,0,0,1);
35         ans+=f[tp][0][0][1];
36     }
37     cout<<ans<<endl;
38     return 0;
39 }
View Code

猜你喜欢

转载自www.cnblogs.com/liankewei/p/10587697.html