给定两个整数 l 和 r ,对于所有满足1 ≤ l ≤ x ≤ r ≤ 10^9 的 x ,把 x 的所有约数全部写下来。对于每个写下来的数,只保留最高位的那个数码。求1~9每个数码出现的次数。
输入描述:
一行,两个整数 l 和 r (1 ≤ l ≤ r ≤ 10^9)。
输出描述:
输出9行。 第 i 行,输出数码 i 出现的次数。
示例1
输入
1 4
输出
4 2 1 1 0 0 0 0 0
题解讲的很清楚。相当于把题目转化为如何快速求cf有一个类似的题目,求法也差不多
题目:http://codeforces.com/contest/616/problem/E
http://blog.youkuaiyun.com/jerans/article/details/72841424
要点1:思维转化,从因子角度考虑
要点2:分块优化,细节难处理一些
#include<bits/stdc++.h>
#define eps 1e-9
#define PI 3.141592653589793
#define bs 1000000007
#define bsize 256
#define MEM(a) memset(a,0,sizeof(a))
typedef long long ll;
using namespace std;
long long ans[2][15];
void slove(long long x,int index)
{
long long sqrt_x;
for(sqrt_x=1;sqrt_x*sqrt_x<=x;sqrt_x++);
sqrt_x--;
for(long long t=1;t<=x;t*=10)
{
for(long long i=1;i<=9&&i*t<=x;i++)
{
long long r=min(x,i*t+t-1);
for(long long d=i*t;d<=min(r,sqrt_x);d++)
{
ans[index][i]+=x/d;
}
if(r<=sqrt_x)
continue;
for(long long k=x/r;k<x/sqrt_x;k++)
{
long long ll=x/(k+1),rr=x/k;
if(min(rr,r)<=max(ll,i*t-1))
continue;
ans[index][i]+=k*(min(rr,r)-max(ll,i*t-1));
}
}
}
return ;
}
int main()
{
long long l,r;
cin>>l>>r;
slove(r,1);
slove(l-1,0);
for(int i=1;i<=9;i++)
{
cout<<ans[1][i]-ans[0][i]<<endl;
}
return 0;
}