数码

1.解释:

1.最先想到的就是直接模拟了,引用每日一题的例子:
eg:l=3 r=6:
x=3 因子有1 3
x=4 因子有1 2 4
x=5 因子有1 5
x=6 因子有1 2 3 6
会发现当确定一个因子1时,另外一个因子为3,4,5,6(6=6/1);当确定一个因子2时,另外一个因子为3
eg:l=1 r=6:
x=1 因子有1
x=2 因子有1 2
x=3 因子有1 3
x=4 因子有1 2 4
x=5 因子有1 5
x=6 因子有1 2 3 6
会发现当确定一个因子1时,另外一个因子为2,3,4,5,6(6=6/1);当确定一个因子2时,另外一个因子为3
观察枚举的过程就可以发现以下几点:
1.x是什么还有x的因子是谁都不重要;
2.x=a*b,其中 a图片说明 a<=x(完全平方数有一对a=b的情况,所以可以设置b的左边界不小于a+1)。
3.如果我们固定了 a图片说明 b 当中的a,那么x在[L,r]的范围内取值时,可以取到的b是连续的,如a=2,x∈[3,6],b可以取2,3,所以就可以直接求出位数和最高位确定的b的区间,然后这个最高位出现的次数加上区间的长度。
4.a出现的次数就是对应b的区间的长度,提取出a的最高位,然后这个最高位出现的次数加上b区间的长度
为了求解方便,我们先求出[1,r],再求[1,L-1],最后的答案就是[1,r]-[1,L-1]。
答案一定要用long long,不然只能过85%。

2.代码:
#include <bits/stdc++.h>
#define ll long long
#define  js  ios::sync_with_stdio(false);cin.tie(0);cout.tie(0)
using namespace std;
ll a[10],b[10];
int shou(int x) {
    int ans=0;
    while(x) {
        ans=x%10;
        x/=10;
    }
    return ans;
}
void solve(int r,ll a[]) {
    for(int i=1;i*i<=r;++i) {        //枚举全部的因子 
        int b=r/i;
        for(int j=1;j<=r;j*=10)        //枚举位数 
            for(int k=1;k<=9;++k) { //枚举首位 
                int x=max(k*j,i+1),y=min(k*j+j-1,b);
                if(y>=x)    a[k]+=y-x+1;
            }
        int temp=shou(i);
        a[temp]+=b-i+1;
    }
}
ll l,r;
int main() {
    js;
    cin>>l>>r;
    solve(r,a);
    solve(l-1,b);
    for(int i=1;i<=9;++i)    cout<<a[i]-b[i]<<endl;
    return 0;
}