题目大意:求1-N-1之间和N互质的数的四次方和
快速幂求逆元
容斥原理
素数打表
素因子分解
二进制枚举子集
高次求和
这里有一个公式
也可以现推
由三次推N^2
由五次推N^4
大体思路就是素因子分解得到的因子组合,然后用到容斥原理,奇数个因子的情况加到一起,偶数个因子的情况减,然后求高次和的时候,涉及到取模所以要求1e9的逆元,最后得到非互素的数的四次方和,然后用所有数的四次方和,减掉非素数的四次方和。需要注意可能会出现负的情况 要加mod再取模。
#include <iostream>
#include <string.h>
#include <stdio.h>
#include <math.h>
using namespace std;
const int mod=1e9+7;
const int maxn=1e6+5;
int prime[maxn];
int vis[maxn],cnt,p;
typedef long long ll;
ll gcd(ll n, ll m)
{
if(m==0)
return n;
else
return gcd(m,n%m);
}
void init()
{
cnt = 0;
memset(vis,0,sizeof(vis));
for(int i=2; i<maxn; i++)
{
if(!vis[i])
{
prime[cnt++]=i;
for(int j=i+i; j<maxn; j+=i)
vis[j]=1;
}
}
}
int yz[maxn];
void syzfj(ll n)
{ p=0;ll x=n;
for(int i=0; i<cnt&&prime[i]*prime[i]<=n; i++)
{ ll tmp=0;
if(n%prime[i]==0)
{
yz[p]=prime[i];
while(x%prime[i]==0)
{
tmp++;
x/=prime[i];
}
p++;
}
}
if(x>1)
{
yz[p]=x;
p++;
}
}
ll quickmod(ll n,ll m,ll tt)
{
ll ans=1;
while(m)
{
if(m&1)
ans=ans*n%tt;
m>>=1;
n=n*n%tt;
}
return ans;
}
ll qh(ll n)
{
ll tmp1=n%mod;
ll tmp2=tmp1*(n+1)%mod;
ll tmp3=tmp2*(2*n+1)%mod;
ll tmp4=((3*(n+1)%mod)*n%mod)-1;
ll ans=(tmp3*tmp4%mod)%mod*quickmod(30,mod-2,mod)%mod;
return ans%mod;
}
int main()
{
int n,t;ll ans=0;
cin>>t;
init();
while(t--)
{
cin>>n;
syzfj(n);ans=0;
for(int i=1; i<(1<<p); i++)
{
ll cj=1;int c=0;
for(int j=0; j<p; j++)
{
if(i&(1<<j))
{
c++;
cj=cj*yz[j]%mod;
}
}
if(c%2==0)
ans=(ans-qh(n/cj)*quickmod(cj,4,mod)%mod+mod)%mod;
else
ans=(ans+qh(n/cj)*quickmod(cj,4,mod)%mod+mod)%mod;
}
ans=(qh(n)-ans+mod)%mod;
cout<<ans<<endl;
}
return 0;
}