本来打算一道一道的刷过去,结果发现,最水的题我都想了好久,这道题用容斥来解就好,开始想的版本只是减去了它的因子,结果一直WA,后来细细的想了很久,才发现这是一道容斥,还有一个地方就是这里有一个除30没有注意到这个细节,还有就是这题处处要小心越界。唉,最简单的题,我都不觉得水,更何况是难题呢。
上代码:
#include<cstdio>
#include<cstring>
using namespace std;
long long prime[10010];
long long pnum=0;
long long c[10010];
const long long mod=1000000007;
void getprime(){
memset(c,0,sizeof(c));
for(long long i=2;i<=10000;i++){
if(!c[i]){
prime[pnum++]=i;
for(long long j=i*i;j<=10000;j+=i) c[j]=1;
}
}
}
long long factor[15],fnum=0;
long long f[13];
void cal(){
f[0]=1;
for(long long i=1;i<=12;i++){
f[i]=2*f[i-1];
}
}
long long get(long long n){
long long n3=(((n*n)%mod)*n)%mod,n4=(n3*n)%mod,n5=(n4*n)%mod;
long long sum=((((n5*6+15*n4+10*n3-n)%mod)*233333335)%mod+mod)%mod;
return sum;
}
main(){
long long t,n;
getprime();
cal();
scanf("%lld",&t);
long long tmp=1;
while(t--){
scanf("%lld",&n);
//n=tmp++;
//printf("%lld\n",n);
long long cnt=n;
fnum=0;
for(long long i=0;i<pnum;i++){
if(prime[i]*prime[i]>cnt)
break;
if(cnt%prime[i]==0)
factor[fnum++]=prime[i];
while(cnt%prime[i]==0)
cnt=cnt/prime[i];
}
if(cnt!=1){
factor[fnum++]=cnt;
}
long long m=f[fnum]-1;
long long ans=0;
for(long long i=0;i<=m;i++){
long long flag=0,cnt=1;
for(long long j=0;j<fnum;j++){
if((i&f[j])==f[j]){
flag++;
cnt=cnt*factor[j];
}
}
if(flag%2==0){
ans+=(((((cnt*cnt)%mod)*((cnt*cnt)%mod))%mod)*get(n/cnt))%mod;
}
else
ans-=(((((cnt*cnt)%mod)*((cnt*cnt)%mod))%mod)*get(n/cnt))%mod;
ans=(ans+mod)%mod;
}
printf("%lld\n",ans);
}
}