裸的数位DP
每次枚举最后所有数位上的和是多少,然后数位DP即可
然后hehe那一维是用来表示这一位能否任意取
然后sum表示目前和%所有数位上的和是多少
然后he表示目前所有数的和是多少
然后pos表示还剩下几个位置要填数字
#include<iostream>
#include<algorithm>
#include<cmath>
#include<cstring>
using namespace std;
int bit[20],bit2[20],mod;
long long l,r,ans,dp[20][164][164];
long long dfs1(int pos,int sum,int he,bool hehe){
if(pos==0){
return(he==mod)&&(sum==0);
}
long long fanhui=dp[pos][sum][he];
if(!hehe&&fanhui!=-1){
return fanhui;
}else{
if(he>mod){
fanhui=0;
}else{
int up=hehe?bit[pos]:9;
fanhui=0;
for(int i=0;i<=up;i++){
fanhui+=dfs1(pos-1,(sum*10+i)%mod,he+i,hehe&&i==up);
}
}
if(!hehe){
dp[pos][sum][he]=fanhui;
}
}
return fanhui;
}
long long dfs2(int pos,int sum,int he,bool hehe){
if(pos==0){
return(he==mod)&&(sum==0);
}
long long fanhui=dp[pos][sum][he];
if(!hehe&&fanhui!=-1){
return fanhui;
}else{
if(he>mod){
fanhui=0;
}else{
int up=hehe?bit2[pos]:9;
fanhui=0;
for(int i=0;i<=up;i++){
fanhui+=dfs2(pos-1,(sum*10+i)%mod,he+i,hehe&&i==up);
}
}
if(!hehe){
dp[pos][sum][he]=fanhui;
}
}
return fanhui;
}
int main(){
cin>>l>>r;
for(bit[0]=0;r;r/=10)bit[++bit[0]]=r%10;
for(bit2[0]=0;l;l/=10)bit2[++bit2[0]]=l%10;
for(mod=1;mod<=162;mod++){
memset(dp,-1,sizeof(dp));
ans+=dfs1(bit[0],0,0,1);
memset(dp,-1,sizeof(dp));
ans-=dfs2(bit2[0],0,0,1);
}
cout<<ans<<endl;
return 0;
}
/*
in:
10 19
out:
3
*/