题目传送门
题意: 给出两个数a,b,求出[a,b]中各位数字之和能整除原数的数的个数。
思路: 因为a和b的范围都是 1 0 18 10^{18} 1018,位数和最多能达到18*9=162,所以我们枚举位数和,统计可以整数这个位数和的原数个数,原数必须保证位数和与枚举的一致。考虑使用状态f[pos][sum][mod]记录当搜索到第pos位,原数模位数和为sum,位数和为mod的情况下,到达终点的方案数。
思路:
#include<bits/stdc++.h>
#define endl '\n'
#define mp make_pair
#define pb push_back
#define ll long long
#define int long long
#define pii pair<int,int>
#define sz(x) (int)(x).size()
#define all(x) (x).begin(),(x).end()
#define mem(a,b) memset(a,b,sizeof(a))
char *fs,*ft,buf[1<<20];
#define gc() (fs==ft&&(ft=(fs=buf)+fread(buf,1,1<<20,stdin),fs==ft))?0:*fs++;
inline int read()
{
int x=0,f=1;
char ch=gc();
while(ch<'0'||ch>'9')
{
if(ch=='-')
f=-1;
ch=gc();
}
while(ch>='0'&&ch<='9')
{
x=x*10+ch-'0';
ch=gc();
}
return x*f;
}
using namespace std;
const int N=200;
const int inf=0x3f3f3f3f;
//const int mod=1e9+7;
int a[N],len=0;
int f[20][N][N];
int ans[N][2],now=0;
int dfs(int pos,int lim,int sum,int cnt,int mod) {
if(pos==0)
return sum == 0 && cnt == mod;
if(!lim&&f[pos][sum][cnt]!=-1) return f[pos][sum][cnt];
int high=lim?a[pos]:9,res=0;
for(int i=0; i<=high; i++)
res+=dfs(pos-1,lim&&i==high,(sum*10+i)%mod,cnt+i,mod);
if(!lim) f[pos][sum][cnt]=res;
return res;
}
int work(int x) {
len=0;
while(x)
a[++len]=x%10,x/=10;
for(int i=1; i<=170; i++) {
mem(f,-1);
ans[i][now]=dfs(len,1,0,0,i);
}
now^=1;
}
void solve() {
int l,r;
cin>>l>>r;
work(r);
work(l-1);
int res=0;
for(int i=1; i<=170; i++)
res+=(ans[i][0]-ans[i][1]);
cout<<res<<endl;
}
signed main()
{
solve();
}