题目:
给你一个数,如果这个数能被这个数的各个数位上的数的和整除,那么这个数是beautiful number. 给你一个n, 求从1到n有多少个漂亮数。
输入:
样例T
每行一个n
输出:
小于n的beautiful number 的个数(1 ≤ N ≤ 1e12).
一道数位dp题,感觉数位dp,一般sum值很大,数组肯定开不下,所以要尽可能的压缩sum的值,这道题假设n有len位,所以能整除n的数肯定在[1,9*len]之间,所以sum只需要开到9*12,对区间内的每一个数作为mod,跑一遍dfs,如果结束的时候ans数位之和等于mod,就是漂亮数。dfs里的sum和ans要用int不然会TLE。。。
#include"bits/stdc++.h"
using namespace std;
typedef long long ll;
ll dp[50][205][205];//dp[数位][数值][各数位数之和]
ll dis[505];
int mod;
ll dfs(int pos,int sum,int ans,bool flag){//pos是数位,sum是数值,ans是数位数之和,sum,ans用int
if(pos==0) return ans==mod&&!sum;
if(!flag&&dp[pos][sum][ans]!=-1) return dp[pos][sum][ans];
ll res=0;
int up=flag?dis[pos]:9;
for(int i=0;i<=up;i++){
int ssum=(sum*10+i)%mod;//int
int aans=ans+i;//int
if(aans>mod) break;
res+=dfs(pos-1,ssum,aans,flag&&i==up);
}
if(!flag)
dp[pos][sum][ans]=res;
return res;
}
ll solve(ll n){
int len=0;
while(n){
dis[++len]=n%10;
n/=10;
}
ll res=0;
for(int i=1;i<=9*len;i++){
mod=i;
memset(dp,-1,sizeof(dp));
res+=dfs(len,0,0,true);
}
return res;
}
ll cnt=0;
int c=1;
int main(){
int T;
cin>>T;
int i,j;
while(T--){
ll n;
scanf("%lld",&n);
printf("Case %d: %lld\n",c++,solve(n));
}
return 0;
}