题目描述
给定两个整数
和
。
对于任意 ,满足 ,把 的所有约数全部写下来。
对于每个写下来的数,只保留最高位的那个数码。求 中每个数码出现的次数。
解题思路
对于暴力肯定不可取,优化暴力,考虑枚举数码
,属于数码
的数可以有
所以对于数码
就枚举这些数,然后对于
中
的倍数个数为
然后对于连续的一块区间,
可以进行分块加速。
复杂度O(
)
#pragma GCC optimize(2)
#include<bits/stdc++.h>
using namespace std;
const int man = 2e5+10;
#define IOS ios::sync_with_stdio(0)
template <typename T>
inline T read(){T sum=0,fl=1;int ch=getchar();
for(;!isdigit(ch);ch=getchar())if(ch=='-')fl=-1;
for(;isdigit(ch);ch=getchar())sum=sum*10+ch-'0';
return sum*fl;}
template <typename T>
inline void write(T x) {static int sta[35];int top=0;
do{sta[top++]= x % 10, x /= 10;}while(x);
while (top) putchar(sta[--top] + 48);}
template<typename T>T gcd(T a, T b) {return b==0?a:gcd(b, a%b);}
template<typename T>T exgcd(T a,T b,T &g,T &x,T &y){if(!b){g = a,x = 1,y = 0;}
else {exgcd(b,a%b,g,y,x);y -= x*(a/b);}}
#ifndef ONLINE_JUDGE
#define debug(fmt, ...) {printf("debug ");printf(fmt,##__VA_ARGS__);puts("");}
#else
#define debug(fmt, ...)
#endif
typedef long long ll;
const ll mod = 1e9+7;
ll cal(int n,int a,int b){
ll ans = 0;
for(int l = a,r = 0;l <= min(b,n);l = r + 1){
r = min(b,n / (n / l));
ans += 1ll * (r - l + 1)*(n / l);
}
return ans;
}
ll calc(ll i,int l,int r){
ll ans = 0,tp = 1;
for(int j = 1;i <= r;j *= 10,i *= 10){
ans += cal(r,i,min(1ll * r,i + j - 1)) - cal(l-1,i,min(1ll * r,i + j - 1));
}
return ans;
}
int main() {
#ifndef ONLINE_JUDGE
//freopen("in.txt", "r", stdin);
//freopen("out.txt","w",stdout);
#endif
int l,r;
cin >> l >> r;
for(int i = 1;i <= 9;i++){
printf("%lld\n",calc(i,l,r));
}
return 0;
}