题目链接:
http://acm.hdu.edu.cn/showproblem.php?pid=4059
题意:
给定一个数n求小于n的与n互斥的数的四次方的和。
分析:
我们可以求出从1~n的所有数的四次方的和sum1,然后容斥求出1~n所有与n不互斥的数的四次方的和sum2;
ans =sum1 - sum2;
设f(n)表示从1~n的所有数的四次方的和 f(n)=1/30*n*(n+1)(2n+1)(3n^2+3n-1);
推倒如下:
(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
(n-1)^5-(n-2)^5=5(n-2)^4+10(n-2)^3+10(n-2)^2+5(n-2)+1
...
...
...
2^5-1^5=5*1^4+10*1^3+10*1^2+5*1+1
需要用到的公式有
1^2+2^2+...+n^2=n*(n+1)*(2*n+1)/6;
1^3+2^3+...+n^3=n^2*(n+1)^2/4;
然后全部相加起来,经行化简 就可以就可以得到f(n)
因为要取模,而且有除法因此我们需要求逆元
a^b=1(mod m)
这里介绍两种方法
1)
因为30与1000000007互斥 因此由费马小定理可知这是的逆元为(30^(mod-2))%(mod);
2)
a/b mod m = (a mod (m*b) )/m;
代码如下:
#include <iostream> #include <cstring> #include <cstdio> #include <algorithm> using namespace std; const int mod = 1000000007; typedef long long LL; int cnt=0; int a[50]; LL n,inv; void fen(int n)//素因子分解 { cnt=0; for(int i=2;i*i<=n;i++){ if(n%i==0){ a[cnt++]=i; while(n%i==0) n/=i; } } if(n>1) a[cnt++]=n; } LL multi(LL a,LL b,LL m) { LL ans = 0; while(b){ if(b&1){ ans = (ans + a)%m; b--; } b>>=1; a=a*2; if(a>n) a%=m; } return ans; } LL quick_mod(LL a,LL b,LL m) { LL ans = 1; while(b){ if(b&1){ ans=multi(ans,a,m); b--; } b>>=1; a=multi(a,a,m); } return ans; } LL f(LL n)// 四次方和公式:1/30*n*(n+1)(2n+1)(3n^2+3n-1) { LL ans=n; ans=(ans*(n+1))%mod; ans=(ans*(2*n+1))%mod; ans=(ans*((3*n*n+3*n-1)%mod))%mod; ans=(ans*inv)%mod; return ans; } LL solve(LL n) { fen(n); LL ans = 0; for(int i=1;i<(1<<cnt);i++){ LL tmp = 1; int tt = 0; for(int j=0;j<cnt;j++){ if((1<<j)&i){ tmp=tmp*a[j]; tt++; } } LL q=n/tmp; LL t = multi(multi(tmp,tmp,mod),multi(tmp,tmp,mod),mod); if(tt&1) ans=(ans+multi(f(q),t,mod))%mod; else ans=(ans-multi(f(q),t,mod)+mod)%mod; } return ans; } int main() { int t; scanf("%d",&t); while(t--){ scanf("%I64d",&n); if(n==1){ puts("0"); continue; } inv = quick_mod(30,mod-2,mod); LL tmp = f(n); LL ans = solve(n); ans=(tmp-ans+mod)%mod; printf("%I64d\n",ans); } return 0; }
时间: 2024-11-05 11:23:12