loj 6083.「美团 CodeM 资格赛」数码

题目:

给定两个整数(l)(r),对于任意(x),满足(lleq xleq r),把(x)所有约数写下来。
对于每个写下来的数,只保留最高位的那个数码。求([1,9])中每个数码出现的次数.
(1 leq l leq r leq 10^9)

题解:

转化成统计贡献。
考虑每个数落在区间内多少次。
将每种数码分开考虑即可。
由于每种数码的数的区间不是连续的,所以枚举一下即可。

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
typedef long long ll;
inline void read(int &x){
    x=0;char ch;bool flag = false;
    while(ch=getchar(),ch<'!');if(ch == '-') ch=getchar(),flag = true;
    while(x=10*x+ch-'0',ch=getchar(),ch>'!');if(flag) x=-x;
}
#define rg register int
#define rep(i,a,b) for(rg i=(a);i<=(b);++i)
#define pre(i,a,b) for(rg i=(a);i>=(b);--i)
inline ll solve(int n,int l,int r){
    ll ret = 0;
    for(rg i = l,j = i;i <= r;i = j+1){
    	j = n/(n/i);j = min(j,r);
    	ret += 1LL*(j-i+1)*(n/i);
    }return ret;
}
inline ll query(int n,int k){
    ll ans = 0,x = k,y = 1;
    while(x <= n){
    	ans += solve(n,x,min(x+y-1,1LL*n));
    	x *= 10;y *= 10;
    }return ans;
}
int main(){
    int l,r;read(l);read(r);
    rep(i,1,9){
	    printf("%lld
",query(r,i) - query(l-1,i));
    }
    return 0;
}
原文地址:https://www.cnblogs.com/Skyminer/p/7067354.html