数码
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; }