题目链接
思路:显然暴力的做法是for i:1-r 看在[l,r]内有多少个数是是i的倍数。
for(int i=1;i<=r;i++){
ans[get(i)]+=r/i-(l-1)/i;//get()为获取i的第一个数码
} 怎么优化呢?
观察暴力的式子我们可以发现:r/i和(l-1)/i是两个除法的式子。显然是可以除法分块的。
这样就可以把正贡献和负贡献分开用除法分块计算。
统计答案的时候模拟一下即可。
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N = 2e5 + 10;
#define fi first
#define se second
#define pb push_back
LL cnt[55],fac[13];
void add(int l,int r,int x,int y){
int xx=0,yy=0,g1=0,g2=0,R=r,L=l;//cout<<l<<' '<<r<<endl;
while(l){
g1=l%10;
l/=10;
xx++;
}
while(r){
g2=r%10;
r/=10;
yy++;
}
if(xx==yy && g1==g2){
cnt[g1]+=1ll*y*x*(R-L+1);
}else if(xx==yy && g1!=g2){
for(int i=g1+1;i<g2;i++){
cnt[i]+=1ll*y*x*fac[xx-1];
}
cnt[g1]+=1ll*y*x*(1ll*(g1+1)*fac[xx-1]-L);
cnt[g2]+=1ll*y*x*(R-1ll*g2*fac[yy-1]+1);
}else{
for(int i=xx;i<yy-1;i++){
for(int j=1;j<=9;j++){
cnt[j]+=1ll*y*x*fac[i];
}
}
for(int i=g1+1;i<=9;i++){
cnt[i]+=1ll*y*x*fac[xx-1];
}
for(int i=1;i<g2;i++){
cnt[i]+=1ll*y*x*fac[yy-1];
}
cnt[g1]+=1ll*y*x*(1ll*(g1+1)*fac[xx-1]-L);
cnt[g2]+=1ll*y*x*(R-1ll*g2*fac[yy-1]+1);
}
}
int l,r;
int main() {
ios::sync_with_stdio(false);
fac[0]=1;
for(int i=1;i<=10;i++)fac[i]=fac[i-1]*10;
cin>>l>>r;
l--;
for(int i=1,j;i<=r;i=j+1){
j=r/(r/i);
add(i,j,r/i,1);
}
for(int i=1,j;i<=l;i=j+1){
j=l/(l/i);
add(i,j,l/i,-1);
}
for(int i=1;i<=9;i++)cout<<cnt[i]<<'\n';
return 0;
} 
京公网安备 11010502036488号