2705: [SDOI2012]Longge的问题
Time Limit: 3 Sec Memory Limit: 128 MBSubmit: 2504 Solved: 1528
[ Submit][ Status][ Discuss]
Description
Longge的数学成绩非常好,并且他非常乐于挑战高难度的数学问题。现在问题来了:给定一个整数N,你需要求出∑gcd(i, N)(1<=i <=N)。
Input
一个整数,为N。
Output
一个整数,为所求的答案。
Sample Input
6
Sample Output
15
HINT
【数据范围】
对于60%的数据,0<N<=2^16。
对于100%的数据,0<N<=2^32。
Source
任意枚举n的一个约数k,那么k对答案的贡献是多少??
k*phi(n/k)其中phi为欧拉函数。。。
那么我们就要求∑k*phi(n/k) (k|n)
约数的话,根号级别枚举,,欧拉函数可以用log级计算
预处理n的所有质因数(小于sqrt(n)的),用这些质因数去搞当前要求的phi(x)就行了
返回的时候没乘以x-1,,漏了大素数。。GG
#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
using namespace std;
const int maxn = (1<<16) + 1;
typedef long long LL;
int N,tot;
bool not_prime[maxn];
LL n,ans,prime[maxn];
LL phi(LL x)
{
if (x == 1) return 1;
LL ret = 1;
for (int i = 1; i <= N; i++)
if (x % prime[i] == 0) {
ret *= (prime[i]-1);
x /= prime[i];
while (x % prime[i] == 0) ret *= prime[i],x /= prime[i];
}
if (x > 1) ret = ret*(x-1);
return ret;
}
int main()
{
#ifdef DMC
freopen("DMC.txt","r",stdin);
#endif
cin >> n;
for (int i = 2; i < maxn; i++) {
if (!not_prime[i]) prime[++tot] = i;
for (int j = 1; j <= tot; j++) {
int t = prime[j]*i;
if (t >= maxn) break;
not_prime[t] = 1;
}
}
for (int i = 1; i <= tot; i++)
if (n % prime[i] == 0) prime[++N] = prime[i];
int Sqrt = sqrt(n);
for (LL i = 1; i <= Sqrt; i++) {
if (n % i == 0) {
ans += i*phi(n/i);
if (i != (n/i)) ans += n/i*phi(i);
}
}
cout << ans;
return 0;
}