http://acm.hdu.edu.cn/showproblem.php?pid=4059
本题便是对于利用容斥原理进行欧拉函数的求解的拓展.... n = p1^a1*p2^a2*p3^a3*...*pk^ak
A1表示m的素因子分解中含有素因子p1, .... Ak表示m的素因子分解中含有pk,则与n互质的数A1至Ak性质均不满足,显然可以利用容斥原理来进行求解...
phi(n) = n - |A1| - |A2| - ... - |Ak| + |A1^A2| + ... + (-1)^k|A1^A2^...^Ak|, 显然对于求解与n的互质的数的和、平方和、立方和等等均可以利用该公式来进行相应的求解,只不过将其中元素换成我们需要求解的元素即可(其中对与求解互质的元素的和我们有更简便的答案: ans = n*phi(n)/2)
问题便变的如此的简单:
#include <cmath>
#include <ctime>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long LL;
const int MAXN = 10010;
const LL MOD = 1000000007;
bool is_prime[MAXN];
LL prime[MAXN];
LL factor[MAXN];
int T, len, cnt;
LL ans, n;
void Init()
{
int i, j;
len = 0;
memset(is_prime, true, sizeof(is_prime));
prime[len++] = 2;
for(i = 3; i * i <= MAXN; i += 2)
{
if(is_prime[i])
{
prime[len++] = i;
for(j = i * i; j < MAXN; j += i)
{
is_prime[j] = false;
}
}
}
for( ; i < MAXN; i += 2)
{
if(is_prime[i])
{
prime[len++] = i;
}
}
}
LL mult_mod(LL a, LL b, LL c)
{
LL ret = 0;
while(b)
{
if(b & 1) ret = (ret + a) % c;
a = a * 2 % c;
b >>= 1;
}
return ret;
}
LL power_mod(LL a, LL b, LL c)
{
LL ret = 1;
while(b)
{
if(b & 1) ret = mult_mod(ret, a, c);
a = mult_mod(a, a, c);
b >>= 1;
}
return ret;
}
LL get_sum(LL x)
{
return (((((x*(2*x+1)%MOD)*(x+1))%MOD)*(3*x*x%MOD+3*x-1)%MOD)*power_mod(30,MOD-2,MOD))%MOD;
}
void cal_factor(LL x)
{
cnt = 0;
for(int i = 0; i < len && prime[i] * prime[i] <= x; ++i)
{
if(x % prime[i] == 0)
{
factor[cnt++] = prime[i];
while(x % prime[i] == 0)
x /= prime[i];
}
}
if(x > 1)
{
factor[cnt++] = x;
}
return ;
}
void dfs(int id, LL cur, int ccount)
{
if(id == cnt)
{
if(ccount & 1)
ans = (ans - (power_mod(cur, 4, MOD) * get_sum(n/cur) % MOD))%MOD;
else
ans = (ans + (power_mod(cur, 4, MOD) * get_sum(n/cur) % MOD))%MOD;
return ;
}
dfs(id + 1, cur, ccount);
dfs(id + 1, cur * factor[id], ccount + 1);
return ;
}
int main()
{
//freopen("aa.in", "r", stdin);
//freopen("bb.out", "w", stdout);
Init();
scanf("%d", &T);
while(T--)
{
cin >> n;
cal_factor(n);
ans = 0;
dfs(0, 1, 0);
cout << (ans % MOD + MOD) % MOD << endl;
}
return 0;
}