版权声明:博主写博客也挺不容易,转载当然阔以,记得先吱一声~ https://blog.csdn.net/Cold_Chair/article/details/82533815
Description:
一个合数的真因数是指这个数不包括其本身的所有因数,例如6 的正因数有
1; 2; 3; 6,其中真因数有1; 2; 3。一个合数的最大真因数则是这个数的所有真因数中最大
的一个,例如6 的最大真因数为3。
给定正整数l 和r,请你求出l 和r 之间(包括l 和r)所有合数的最大真因数之和。
题解:
考虑Min_25筛求质数和。
求g的过程中,有一个枚举最小质因子的过程,利用这个就可以求答案了。
#include<cmath>
#include<cstdio>
#define ll long long
#define ul unsigned long long
#define fo(i, x, y) for(int i = x; i <= y; i ++)
using namespace std;
const int N = 2e5 + 5;
ll l, r; ul w[N], sp[N], g[N], p[N];
int sqr, m, i1[N], i2[N], bz[N];
ll solve(ll n) {
if(n <= 2) return 0;
sqr = sqrt(n);
fo(i, 2, sqr) bz[i] = 0; p[0] = 0; m = 0;
fo(i, 2, sqr) {
if(!bz[i]) p[++ p[0]] = i, sp[p[0]] = sp[p[0] - 1] + i;
for(int j = 1; i * p[j] <= sqr; j ++) {
bz[i * p[j]] = 1;
if(i % p[j] == 0) break;
}
}
for(ll i = 1, j; i <= n; i = j + 1) {
j = n / (n / i); w[++ m] = n / i;
if(w[m] <= sqr) i1[w[m]] = m; else i2[n / w[m]] = m;
g[m] = (w[m] + 2) * (w[m] - 1) / 2;
}
ul ans = 0;
fo(j, 1, p[0]) for(int i = 1; i <= m && p[j] * p[j] <= w[i]; i ++) {
int k = (w[i] / p[j] <= sqr) ? i1[w[i] / p[j]] : i2[n / (w[i] / p[j])];
g[i] -= p[j] * (g[k] - sp[j - 1]);
if(i == 1) ans += g[k] - sp[j - 1];
}
return ans;
}
int main() {
freopen("factor.in", "r", stdin);
freopen("factor.out", "w", stdout);
while(scanf("%lld %lld", &l, &r) != EOF)
printf("%lld\n", solve(r) - solve(l - 1));
}