题意:求小于n的与n互素的数的四次方的和对1e9+7取模。
思路:我们还是考虑一下逆问题,求小于n的与n不互素的数的四次方和,所以还是枚举n的素因子,再用容斥原理,这里需要一个公式就是1+2^4+3^4+...+n^4,百度一下就可以得到,简单推导一下,利用了累加法,考虑了比四次方高一次的五次来求
(n+1)^5-n^5=1+5n+10n^2+10n^3+5n^4,那么:
n^5-(n-1)^5=1+5(n-1)+10(n-1)^2+10(n-1)^3+5(n-1)^4,
...
...
2^5-1^5=1+5*1+10*1+10+1+5+1
累加,则左边=(n+1)^5-1=n+5(n+(n-1)+...+1)+10(n^2+(n-1)^2+...+1)+10(n^3+(n-1)^3+...+1)+5(n^4+(n-1)^4+...+1)=右边
其中n^3+(n-1)^3+...+1也用类似的方法,这就可以得到n^4+(n-1)^4+...+1了
最后推得n^4+(n-1)^4+...+1=n*(n+1)*(2*n+1)*(3*n^2+3*n-1)/30
还有我们要求小于n的与n互素的数的四次方的和,那么在枚举n的素因子组合的时候,如果得到一个素因子组合比如mul,那么小于n的是mul的倍数的数的四次方的和为(1+2^4+...+(n/mul)^4)*mul^4,这样就免去循环计算的麻烦
完整代码:
#include <cstdio>
#include <cstring>
#include <iostream>
#include <vector>
using namespace std;
typedef long long LL;
const int mod=1e9+7;
vector<int> p;
LL quickmod(LL a,LL b)
{
a=a%mod;
LL ans=1;
while(b)
{
if(b&1)
{
ans=ans*a%mod;
}
b>>=1;
a=a*a%mod;
}
return ans;
}
LL getpow(LL n)///1+2^4+3^4+4^4+...+n^4
{
LL ans=((n*(n+1)%mod)*(2*n+1)%mod)*(3*((n*n)%mod)+3*n-1)%mod;
ans=ans*quickmod(30LL,mod-2);
return ans%mod;
}
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
LL n;
scanf("%lld",&n);
p.clear();
int temp=n;
for(int i=2;i*i<=temp;i++)
{
if(temp%i==0)
{
p.push_back(i);
while(temp%i==0)
{
temp/=i;
}
}
}
if(temp>1) p.push_back(temp);
LL S=0;
for(int i=1;i<(1<<p.size());i++)
{
LL mul=1;
LL cnt=0;
for(int j=0;j<p.size();j++)
{
if(i&(1<<j))
{
cnt++;
mul=mul*p[j]%mod;
}
}
if(cnt&1)
S=(S+getpow(n/mul)*quickmod(mul,4)%mod)%mod;
else
S=(S-getpow(n/mul)*quickmod(mul,4)%mod)%mod;
}
LL ans=getpow(n);
ans=ans-S;
ans=(ans%mod+mod)%mod;
printf("%lld\n",ans);
}
return 0;
}