hdu 45092011年大連現場試合I題(反発原理)
2537 ワード
タイトルリンク:http://acm.hdu.edu.cn/showproblem.php?pid=4059; 題意:nとnの互質の数より小さい四次方和を求める.分析:まず四次方程式と公式を解いて、簡単に押します.
必ず4次方程式の求和式を用いなければならない.次に簡単に証明すると、ここでは3回の方程式の公式を知っていることを前提として、次のパターンに従って2回の公式を利用して3回の公式(x+1)^5=x^5+5*x^4+10*x^3+10*x^3+10*x^2+5*x+1;1=1;2=1;2^5=(1+1)^5=1^5+5+5*1^4+10*1^3+10*1^3+10*1^0*1^2+1;3^5=(2+1)^5=(5=2^4+10*2+10*2+10*2+2+2+2*2+5*2+5*2+5*2*2+2*2*2......(n+1)^5=(n+1)^5=n^5+5*n^4+10*n^3+10*n^2+n^2+5*n^1+1;すべて重ね合わせると(n+1)^5=5*(1^4+2^4+・・・・n^4)+10*(1^3+2^3+・・・+n^3)+10*(1^2+2^2+・・・+n^2)+5*(1+2+2+・・・+n)+n+1;そして(1^3+2^3+2^3+・・・・・n^4)=(n+1)^2*n^2*2 2/4;(1^2+2+2+2+n^2+・・・・・・・・・・・・・・・・)=(n*(n+1)*(2*n+1))/6;代入.簡略化後(1^4+2^4+......+n^4)=(n*(n+1)*(2 n+1)*(3*n*n+3*n-1))/30;
それから30の逆元を解くことです.私は手で計算しました...普通は1回拡張ユークリッドでいいです.
nとの互質の数については,まずnとの非互質の数を求め,その素因子の倍数と素因子積の倍数である.ここでは反発で解く.
反発原理の詳細は、反発原理;
コードは次のとおりです.
必ず4次方程式の求和式を用いなければならない.次に簡単に証明すると、ここでは3回の方程式の公式を知っていることを前提として、次のパターンに従って2回の公式を利用して3回の公式(x+1)^5=x^5+5*x^4+10*x^3+10*x^3+10*x^2+5*x+1;1=1;2=1;2^5=(1+1)^5=1^5+5+5*1^4+10*1^3+10*1^3+10*1^0*1^2+1;3^5=(2+1)^5=(5=2^4+10*2+10*2+10*2+2+2+2*2+5*2+5*2+5*2*2+2*2*2......(n+1)^5=(n+1)^5=n^5+5*n^4+10*n^3+10*n^2+n^2+5*n^1+1;すべて重ね合わせると(n+1)^5=5*(1^4+2^4+・・・・n^4)+10*(1^3+2^3+・・・+n^3)+10*(1^2+2^2+・・・+n^2)+5*(1+2+2+・・・+n)+n+1;そして(1^3+2^3+2^3+・・・・・n^4)=(n+1)^2*n^2*2 2/4;(1^2+2+2+2+n^2+・・・・・・・・・・・・・・・・)=(n*(n+1)*(2*n+1))/6;代入.簡略化後(1^4+2^4+......+n^4)=(n*(n+1)*(2 n+1)*(3*n*n+3*n-1))/30;
それから30の逆元を解くことです.私は手で計算しました...普通は1回拡張ユークリッドでいいです.
nとの互質の数については,まずnとの非互質の数を求め,その素因子の倍数と素因子積の倍数である.ここでは反発で解く.
反発原理の詳細は、反発原理;
コードは次のとおりです.
#include <set>
#include <map>
#include <stack>
#include <queue>
#include <math.h>
#include <vector>
#include <string>
#include <utility>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <iostream>
#include <algorithm>
#include <functional>
using namespace std;
long long ans;
const long long mod=1000000007;
const long long maxn=50;
long long fac[maxn];
long long cnt;
void fen(long long n){
for(long long i=2; i*i<=n; i++){
if(n%i==0){
fac[cnt]=i;
while(n%i==0)n/=i;
cnt++;
}
}
if(n>1)fac[cnt++]=n;
}//
void dfs(long long id,long long k,long long w,long long sumsum){
if(id==cnt+1)return;
long long temp;
for(long long i=w;i<cnt;i++){
temp=sumsum*fac[i];
long long m=k/temp;
long long tmp=(m*(m+1))%mod;
tmp=(tmp*(2*m+1))%mod;
tmp=(tmp*(3*m*m%mod+3*m%mod-1+mod))%mod;
tmp=((tmp*233333335ll)%mod+mod)%mod;
tmp=(tmp*((((temp*temp%mod)*temp%mod)*temp)%mod))%mod;
if(id&1)ans=((ans-tmp)%mod+mod)%mod;
else ans=(ans+tmp)%mod;
dfs(id+1,k,i+1,temp%mod);
}
}//
int main()
{
long long t;
scanf("%I64d",&t);
while(t--){
long long n;
scanf("%I64d",&n);
cnt=0;
fen(n);
ans=(n*(n+1))%mod;
ans=(ans*(2*n+1))%mod;
ans=(ans*(3*n*n%mod+3*n%mod-1+mod))%mod;
ans=((ans*233333335ll)%mod+mod)%mod;
dfs(1,n,0,1);
printf("%I64d
",(ans%mod+mod)%mod);
}
return 0;
}