思路:
一道数位DP的板子题
c o d e code code
#include<iostream>
#include<cstring>
#include<cstdio>
#define ll long long
using namespace std;
ll n, ans, len;
ll f[21][163][163];
ll lim[20], a[20];
inline ll dfs(register ll x, register ll sum, register ll k, register ll r, register ll limit) {
//cout<<x<<' '<<sum<<' '<<k<<' '<<r<<' '<<limit<<endl;
if(x > len && sum == 0 && r == 0) {
f[x][sum][r] = 1;
return 1;
}
if(x > len) {
f[x][sum][r] = 0;
return 0;
}
if(!limit && f[x][sum][r] != -1) return f[x][sum][r];
register ll tmp = 0;
if(limit) {
for(register ll i = 0; i <= lim[x]; ++ i)
if(sum - i >= 0)
tmp += dfs(x + 1, sum - i, k, (r * 10 + i) % k, i == lim[x]);
}
else {
for(register ll i = 0; i <= 9; ++ i)
if(sum - i >= 0)
tmp += dfs(x + 1, sum - i, k, (r * 10 + i) % k, 0);
}
// if(!limit && f[x][k][sum][r] != tmp && f[x][k][sum][r] != -1)
// cout<<"dsfdsafasdf"<<endl;
if(!limit) f[x][sum][r] = tmp;
// cout<<tmp<<endl;
return tmp;
}
int main() {
freopen("number.in", "r", stdin);
freopen("number.out", "w", stdout);
scanf("%lld", &n);
register ll m = n;
while(m != 0) {
++ len;
a[len] = m % 10;
m /= 10;
}
for(register ll i = 1; i <= len; ++ i) lim[i] = a[len - i + 1];
for(register ll i = 1; i <= len * 9; ++ i)
{
memset(f, -1, sizeof(f));
ans += dfs(1, i, i, 0, 1);
}
printf("%lld", ans);
return 0;
}