感受
整数分块真香!
思路
一般询问区间[L, R]的问题要么直接处理,要么分成[1, R]-[1, L - 1]处理。
直接考虑第二种处理方法,怎么求[1,x]的答案呢?
比如我们想求解约数的最高位的那个数码为4的情形
- 4
- [40, 49]
- [400, 499]
...
有什么用呢?
如果一个约数为q,那么区间[1, n]中存在约数为q的有【n/q】(下取整)
是不是想到了,这不是就是傻×分块吗?
复杂度分析
枚举数码O(9)
- 枚举数码对应的区间
- 对于每一个区间,进行整数分块求解
总复杂度最坏为O(9 * 10 * sqrt(n))= O(1e6)
#include <bits/stdc++.h> using namespace std; typedef long long ll; const int maxn = 1e4 + 10; ll l, r; ll solve(ll n, ll i){ ll ans = 0; ans += n / i; ll f = i * 10; ll top = i * 10 + 9; top = min(top, n); ll num; for(; f <= n; f *= 10, top = top * 10 + 9, top = min(top, n)){ for(ll L = f, R; L <= top; L = R + 1){ num = n / L; R = n / num; R = min(top, R); ans += num * (R - L + 1); } } return ans; } int main(){ scanf("%lld%lld", &l, &r); for(ll i = 1; i <= 9; i++){ printf("%lld\n", solve(r, i) - solve(l - 1, i)); } return 0; }