每日一练Day 1
NC13221
数码
题解:
题目要求找到中的所有的数的约数出现的次数,如果存在多位数则只取最高位的贡献。
首先需要知道的一个数学知识是:中出现
i
的约数有个,那么我们就只需要考虑约数的数目。即:
。
但是现在要求我们对于多位数,只需要考虑他的最高位的贡献,那我们就维护一个最高位的数字,每次查询它的最大区间长度即可。
AC代码:
#define _CRT_SECURE_NO_WARNINGS #include<bits/stdc++.h> #define ll long long #define INF 0x3f3f3f3f #define inf -0x3f3f3f3f #define me(a,b) memset(a,b,sizeof(a)) #define PII pair<int,int> #define ull unsigned long long #define ios std :: ios :: sync_with_stdio(false) #define rep(i,a,b) for(int i = a;i <= b;i ++) #define esp 1e-16 #pragma warning(disable:4996) using namespace std; ll read() { ll x = 0, f = 1; char c = getchar(); while (c < '0' || c>'9') { if (c == '-') f = -1; c = getchar(); } while (c >= '0' && c <= '9') { x = x * 10 + c - '0'; c = getchar(); } return x * f; } ll l, r; ll mi[20] = {}; ll solve(ll n, ll x) { ll ans = 0ll; for (ll l = 1ll, r; l <= n; l = r + 1) { r = n / (n / l); ll rep = 0ll; // cout << l << ' ' << r << endl; for (int i = 0; i <= 9; i++) rep += max(0ll, min(r, ((x + 1) * mi[i] - 1)) - max(l, x * mi[i]) + 1); ans += rep * (n / l); } return ans; } int main() { ios; l = read(); r = read(); // cout << r << ' ' << l << endl; mi[0] = 1; for (int i = 1; i < 10; i++) mi[i] = mi[i - 1] * 10; for (int i = 1; i <= 9; i++) cout << solve(r, i) - solve(l - 1, i) << endl; return 0; }