题意:
求解(1~n)区间中与n互质的书的四次方和
题解:
转化为【1,n】的四次方和 - 不与n互质的数的四次方和
其中不与n互质的数
可以转化为求解n的质因子,然后利用容斥原理求解得到所有的与n不互质的数字
比如说30,质因子为 2 3 5
2 的倍数有 2 4 6 8 10.。。。30 提一个2得到 2*(1,2,3,4,5,,,,15)
3 的倍数有 3 6 9 。。。。 30
5的倍数有 5 10 15.。。。。30
2*3 的倍数 6 12 18.。。。。。30
2*5的倍数 10 20 30
3*5的倍数 15 30
2*3*5的倍数 30
然后对每一行的四次方和进行容斥原理求解
每一行可以转化为2 ^4* (1 ^4 + 2^4 +3^4 +.....+ 15^4)这样的形式
就可以求得答案了
注意:
本题求解的时候一定要注意防止溢出后再取模
传值的时候也全部需要传long long型的数据类型,最好把所有数据类型都定义成long long
四次方求和公式里面先取模再除以30,因此要求得30的模逆元,即:分子乘以30的模逆元
四次方求和公式:
(n+1)^5-n^5=5n^4+10n^3+10n^2+5n+1 n^5-(n-1)^5=5(n-1)^4+10(n-1)^3+10(n-1)^2+5(n-1)+1 …… 2^5-1^5=5*1^4+10*1^3+10*1^2+5*1+1 全加起来 (n+1)^5-1^5=5*(1^4+2^4()+3^4+4^4+……+n^4)+10*(1^3+2^3+3^3+4^3+……+n^3)+10*(1^2+2^2+3^2+4^4+……+n^2)+5*(1+2+3+4+……+n)+n 因为1^3+2^3+3^3+4^3+……+n^3=[n(n+1)/2]^2 1^2+2^2+3^2+4^4+……+n^2=n(n+1)(2n+1)/6 1+2+3+4+……+n=n(n+1)/2 所以1^4+2^4+3^4+4^4+……+n^4 ={[(n+1)^5-1^5]-10*[n(n+1)/2]^2-10*n(n+1)(2n+1)/6-5*n(n+1)/2-n}/5 =n(n+1)(2n+1)(3n^2+3n-1)/30
模逆元:
//------------模逆元--------------// LL qpowMod(LL m,LL n,LL p) { LL ans=1; LL temp=m; while(n>0) { if(n&1) ans=ans*temp%p; temp=temp*temp%p; n>>=1; } return ans; } LL getInverse(LL a,LL p) { return qpowMod(a,p-2,p); } //--------------------------------//求解质因子:
//-----------求质因子-------------// void devide(LL n) { tot=0; for(LL i=2;i*i<=n;i++){ if(n%i==0){ a[tot++]=i; while(n%i==0) n=n/i; } } if(n>1)//这里要记得 a[tot++]=n; } //--------------------------------//
#include<stdio.h> #include<string.h> #include<algorithm> using namespace std; #define LL long long const LL mod=1000000007; int a[100],tot; LL num; //------------模逆元--------------// LL qpowMod(LL m,LL n,LL p) { LL ans=1; LL temp=m; while(n>0) { if(n&1) ans=ans*temp%p; temp=temp*temp%p; n>>=1; } return ans; } LL getInverse(LL a,LL p) { return qpowMod(a,p-2,p); } //--------------------------------// //-----------求质因子-------------// void devide(LL n) { tot=0; for(LL i=2;i*i<=n;i++){ if(n%i==0){ a[tot++]=i; while(n%i==0) n=n/i; } } if(n>1)//这里要记得 a[tot++]=n; } //--------------------------------// LL calc(LL n) { LL ans=n; ans=ans*(n+1)%mod; ans=ans*(2*n+1)%mod; ans=ans*((3*n*n%mod+3*n-1)%mod)%mod; ans=(ans*num)%mod; return ans; } //--------------------------------// LL power(LL x) { return (((x*x)%mod*x)%mod*x)%mod; } //--------------------------------// //----------容斥原理--------------// LL deal(LL n) { LL ans=0; for(LL i=1;i<(1LL<<tot);i++) { int sum=0,temp=1; for(int j=0;j<tot;j++) { if(i&(1LL<<j)){ sum++; temp=(temp*a[j])%mod; } } if(sum&1) ans=(ans%mod+(calc(n/temp)%mod*power(temp))%mod)%mod; else ans=(ans%mod-(calc(n/temp)%mod*power(temp))%mod+mod)%mod; } return ans; } //--------------------------------// int main() { LL T,n; num=getInverse(30,mod);//求逆元 //freopen("in.txt","r",stdin); scanf("%lld",&T); while(T--) { scanf("%lld",&n); if(n==1){ puts("0"); continue; } devide(n); LL t1=calc(n); LL t2=deal(n); printf("%lld\n",(t1-t2+mod)%mod); } return 0; }
用队列进行容斥原理似乎快了一倍啊 #include<stdio.h> #include<string.h> #include<algorithm> using namespace std; #define LL long long #define MAXN 1000000 const LL mod=1000000007; int a[MAXN],tot; LL num; //------------模逆元--------------// LL qpowMod(LL m,LL n,LL p) { LL ans=1; LL temp=m; while(n>0) { if(n&1) ans=ans*temp%p; temp=temp*temp%p; n>>=1; } return ans; } LL getInverse(LL a,LL p) { return qpowMod(a,p-2,p); } //--------------------------------// //-----------求质因子-------------// void devide(LL n) { tot=0; for(LL i=2;i*i<=n;i++){ if(n%i==0){ a[tot++]=i; while(n%i==0) n=n/i; } } if(n>1)//这里要记得 a[tot++]=n; } //--------------------------------// LL calc(LL n) { LL ans=n*(n+1)%mod; ans=(ans*((2*n%mod+1)%mod))%mod; LL temp=3*(n*n%mod); temp=(temp%mod+3*n%mod-1)%mod; ans=(ans*temp)%mod; return ans*num%mod; } //--------------------------------// LL power(LL x) { return (((x*x)%mod*x)%mod*x)%mod; } //--------------------------------// //----------容斥原理--------------// LL deal(LL n) { LL que[10000],pos=0,sum=0; int q[10000]; q[pos]=1; que[pos++]=-1; for(LL i=0;i<tot;i++){ LL k=pos; for(LL j=0;j<k;j++){ LL temp=power(q[j]*a[i]); q[pos]=q[j]*a[i]%mod; LL t; if(que[j]>0) t=temp%mod; else t=-temp%mod; que[pos]=t*(-1)*calc(n/q[pos]); if(que[pos]>0) que[pos]=que[pos]%mod; else que[pos]=-((-que[pos])%mod); pos++; } } for(LL i=1;i<pos;i++) sum=(sum+que[i])%mod; return sum; } //--------------------------------// int main() { LL T,n; num=getInverse(30,mod);//求逆元 // freopen("in.txt","r",stdin); scanf("%lld",&T); while(T--) { scanf("%lld",&n); if(n==0){ puts("0"); continue; } devide(n); LL temp=calc(n); LL t=deal(n); printf("%lld\n",(temp-t+mod)%mod); } return 0; }