Description:
话说PS总是有着各种各样的烦恼,这天,他又在为自己失败的感情史烦恼着。这时,他心中的女神,魔法少女小圆从天而降,她对他说,如果你能帮我解决一个问题,我就让你永远没有烦恼。
问题是这样的:
寻找一个最大的k,使得存在一个x使得x^k=y,那么f(y)=k,即y最多可以开k次方根。
小圆的要求是求出从a到b的f值之和(包括a和b)。
Input:
多组数据,每组数据一行包含两个数a,b,文件以0 0(不需要输出)结尾。
Output:
每组数据一行表示这一段f值之和。
Sample Input:
2 10
248832 248832
0 0
Sample Output:
13
5
Data Constraint:
30%的数据满足:a<=1000 b<=1000
100%的数据满足:2<=a<=b<=10^18
题目大意:
设x=∏pq
d(x)=gcd(q…)
Ans=∑bi=af(i)
题解:
莫比乌斯反演。
设f(d)=∑ni=2(d(i)==d)
g(d)=∑⌊n/d⌋i=1f(i∗d)
=dn√−1
f(d)=∑⌊n/d⌋i=1g(i∗d)∗μ(i)
f(d)=∑⌊n/d⌋i=1(i∗dn√−1)∗μ(i)
Ans=∑log2(n)i=1i∗f(i)
=∑log(n)i=1i∗∑⌊n/i⌋j=1(i∗jn√−1)∗μ(j)
设T = i *j
Ans=∑nT=1(Tn√−1)∑d|Td∗μ(T/d)
=∑nT=1(Tn√−1)∗φ(T)
要使(Tn√−1) 不等于0,缩小循环范围。
=∑log2(n)T=1(Tn√−1)∗φ(T)
对于每一个询问,可以在log时间内回答。
Code:
#include<cmath>
#include<cstdio>
#define ll long long
#define fo(i, x, y) for(int i = x; i <= y; i ++)
using namespace std;
ll a, b, phi[65];
int gcd(int a, int b) {return b == 0 ? a : gcd(b, a % b);}
ll sum(ll n) {
ll ans = 0;
fo(i, 1, log2(n)) ans += ((ll)pow(n, (long double)1 / i) - 1) * phi[i];
return ans;
}
int main() {
phi[1] = 1; fo(i, 1, 64) fo(j, i + 1, 64) if(gcd(i, j) == 1) phi[j] ++;
for(scanf("%lld %lld", &a, &b); a != 0 || b != 0; scanf("%lld %lld", &a, &b))
printf("%lld\n", sum(b) - sum(a - 1));
}