题目大意是求1-n中与n互质的数的四次方累加。
由于正解比较麻烦,所以我们可以先求出1-n的前n个四次方累加,减去跟n不是互质的数的四次方
1-n的四次方累加和公式 = n*(n+1)*(2*n+1)*(3*n*n+3*n-1)/30
先将n的质因数求出,然后比n小的并且是质因数的倍数的数的四次方 ,由于会多减去一些数,因此要用到容斥定理。
例如2 的倍数有2,4,6,8 。3 里面的倍数也有6,因此会多减。
2的倍数四次方可以提取出来2的次数方,并用1-n/2的四次方累加和公式。
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<vector>
using namespace std;
#define MOD 1000000007
#define ll long long
const int maxn = 1e4 + 5;
vector<ll> q;
int prime[maxn];
int vis[maxn];
int cnt;
ll pow_k(ll a, ll b)
{
ll res = 1;
while(b)
{
if(b & 1)
res =(res*a) % MOD;
a = (a*a)%MOD;
b >>= 1;
}
return res%MOD;
}
ll pow_f(ll x)
{
ll res = (x*x) % MOD;
res = (res * x) %MOD;
res = (res * x) % MOD;
return res % MOD;
}
ll sum(ll n)
{
ll res = pow_k(30, MOD-2);
ll s = n*(n+1) % MOD;
s = (s*(2*n+1)%MOD) % MOD;
s = (s*(3*n*n%MOD + 3*n%MOD-1+MOD)%MOD) % MOD;
s = (s*res) % MOD;
return s%MOD;
}
ll dfs(int index, ll n)
{
ll res = 0, temp;
int len = q.size();
for(int i = index; i< len; i++)
{
temp = q[i];
res = (res + sum(n/temp)*pow_f(temp)%MOD) % MOD;
res = (res - dfs(i+1, n/temp)*pow_f(temp)% MOD + MOD) % MOD;
}
return res % MOD;
}
void is_prime()
{
memset(vis, 0, sizeof vis);
for(int i = 2; i <= maxn; i ++)
{
if(vis[i])
continue ;
prime[cnt++] = i;
for(int j = i*i; j <= maxn; j+=i)
vis[j] = 1;
}
}
int main()
{
int t;
scanf("%d", &t);
while(t--)
{
cnt = 0;
is_prime();
ll n;
q.clear();
scanf("%lld", &n);
ll temp = n;
for(int i = 0; i < cnt && prime[i] < temp; i++)
if(temp%prime[i] == 0)
{
q.push_back(prime[i]);
while(temp%prime[i] == 0)
temp /= prime[i];
}
if(temp != 1)
q.push_back(temp);
ll res = 0;
int size = q.size();
for(int i = 1; i < (1 << size); i++) // 容斥原理
{
int flag = 0;
temp = 1;
for(int j = 0; j < size; j++)
{
if(i & (1 << j))
temp = (temp*q[j]) % MOD,flag = !flag;
}
ll t = (sum(n/temp)*pow_f(temp)) % MOD;
if(flag)
res = (res + t) % MOD;
else
res = (res - t + MOD) % MOD;
}
printf("%lld\n", (sum(n)-res + MOD) % MOD);
//ll res = (sum(n) - dfs(0, n)%MOD + MOD) % MOD;
//cout << res << endl;
// dfs 是递归式 实现容斥原理
}
return 0;
}