由题知:
g(n)=sigma{phi(n/d)*n/d},d|n
f(n)=(g(n)+1)/2
由于欧拉函数的积性,phi(n*m)=phi(n)*phi(m),gcd(n,m)=1
所以,n=pi(pi^ci)
故g(n)=g(pi(pi^ci))。
g(n)=pi(g(pi^ci)
g(pi^ci)=sigma(phi(pi^ci)pi^ci)
而对于phi(pi^ci)(pi-1)*(pi^(ci-1)
至此就这题就解决了!
我的代码:
超时的代码:
LL sumlcm(int n) {
int te = 0, temp = n;
LL sum = 0;
if (n == 1)
return 1;
te = (int) sqrt(n * 1.0);
sum = (LL) n;
for (int i = 2; i <= te; i++) {
if (n % i == 0) {
sum = sum / i * (i - 1);
while (n % i == 0) {
n /= i;
}
}
}
if (n > 1) {
sum = sum / n * (n - 1);
}
return sum * temp / 2;
}
void solve(int n) {
int i, te, temp;
LL sum;
te = (int) sqrt(n * 1.0);
for (i = 1, sum = 0; i <= te; i++) {
if (n % i == 0) {
temp = n / i;
sum += sumlcm(temp);
if (i != temp) {
sum += sumlcm(i);
}
}
}
printf("%I64d\n", sum);
}
AC Code:
#include<stdio.h>
#include<string.h>
#include<math.h>
#define LL long long
#define nmax 44725
int flag[nmax], prime[nmax], plen;
void mkprime() {
memset(flag, -1, sizeof(flag));
int i, j;
for (i = 2, plen = 0; i < nmax; i++) {
if (flag[i]) {
prime[plen++] = i;
}
for (j = 0; (j < plen) && (i * prime[j] < nmax); j++) {
flag[i * prime[j]] = 0;
if (i % prime[j] == 0) {
break;
}
}
}
}
int getPow(int a, int b) {
int res;
res = 1;
while (b) {
if (b & 1) {
res = res * a;
}
a = a * a;
b >>= 1;
}
return res;
}
int getpPhi(int p, int c) {
if (c == 0) {
return 1;
}
return (p - 1) * getPow(p, c - 1);
}
LL calc(int p, int c) {
int i;
LL temp, sum;
for (i = 0, sum = 0LL, temp = 1LL; i <= c; i++) {
sum += temp * getpPhi(p, i);
temp = temp * p;
}
return sum;
}
void solve(int n) {
int i, te, cnt;
LL res;
te = (int) (sqrt(n * 1.0));
for (i = 0, res = 1LL; (i < plen) && (prime[i] <= te); i++) {
if (n % prime[i] == 0) {
cnt = 0;
while (n % prime[i] == 0) {
cnt++;
n /= prime[i];
}
res = res * calc(prime[i], cnt);
}
}
if (n > 1) {
res = res * calc(n, 1);
}
printf("%lld\n", (res + 1) / 2);
}
int main() {
#ifndef ONLINE_JUDGE
freopen("data.in", "r", stdin);
#endif
int n;
mkprime();
while (scanf("%d", &n) != EOF) {
solve(n);
}
return 0;
}
#include<stdio.h>
#include<string.h>
#include<math.h>
#define LL long long
#define nmax 44725
int flag[nmax], prime[nmax], plen;
void mkprime() {
memset(flag, -1, sizeof(flag));
int i, j;
for (i = 2, plen = 0; i < nmax; i++) {
if (flag[i]) {
prime[plen++] = i;
}
for (j = 0; (j < plen) && (i * prime[j] < nmax); j++) {
flag[i * prime[j]] = 0;
if (i % prime[j] == 0) {
break;
}
}
}
}
LL getPow(int a, int b) {
LL res, temp;
res = 1, temp = (LL) a;
while (b) {
if (b & 1) {
res = res * temp;
}
temp = temp * temp;
b >>= 1;
}
return res;
}
LL calc(int p, int c) {
LL res;
res = getPow(p, 2 * c);
res--;
res = res / (p + 1);
res = res * p;
res++;
return res;
}
void solve(int n) {
int i, te, cnt;
LL res;
te = (int) (sqrt(n * 1.0));
for (i = 0, res = 1LL; (i < plen) && (prime[i] <= te); i++) {
if (n % prime[i] == 0) {
cnt = 0;
while (n % prime[i] == 0) {
cnt++;
n /= prime[i];
}
res = res * calc(prime[i], cnt);
}
}
if (n > 1) {
res = res * calc(n, 1);
}
printf("%lld\n", (res + 1) / 2);
}
int main() {
#ifndef ONLINE_JUDGE
freopen("data.in", "r", stdin);
#endif
int n;
mkprime();
while (scanf("%d", &n) != EOF) {
solve(n);
}
return 0;
}