有趣的数(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 N≤106;
对于 30% 30 \% 30% 的数据,N≤109 N leq 10^9 N≤109;
对于 60% 60 \% 60% 的数据,N≤1012 N leq 10^{12} N≤1012;
对于 100% 100 \% 100%的数据,1≤N≤1018 1 leq N leq 10^{18} 1≤N≤1018。
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 }