傳送門
有了拉格朗日插值求自然數冪和,就算要好寫也有差分法可以用,OI裏面伯努利數還有什麼用。
當數據範圍不大,但是需要多次求出具體系數的時候,伯努利數就有用了。
在 預處理組合數和 的逆元之後,利用伯努利數可以 求出 次方冪和的多項式係數,這是拉格朗日插值和差分法不好做到的(當然也有可能是我菜)。
算了,不扯了,推出來就知道爲什麼拉格朗日插值和差分法不好做了。
題解:
拿到式子先進行套路的化簡:
前面的常數丟掉,考慮後面的:
設多項式 ,其中 表示多項式的係數。
繼續轉化
不難發現後面是狄利克雷卷積的形式,函數爲
這是個積性函數,所以我們把多項式係數求出來,把 進行質因數分解,然後求質因子點值即可。
還剩的問題就是求質因子點值。
不難發現,由於中間有一個 所以中間的指數只需要考慮 就行了。
有點卡常,Pollard-Rho 需要優化,當然要是你用什麼玄學分解也行。
代碼:
#include<bits/stdc++.h>
#define ll long long
#define re register
#define cs const
using std::cerr;
using std::cout;
cs int mod=1e9+7;
inline int add(int a,int b){return a+b>=mod?a+b-mod:a+b;}
inline int dec(int a,int b){return a-b<0?a-b+mod:a-b;}
inline int mul(int a,int b){ll r=(ll)a*b;return r>=mod?r%mod:r;}
inline void Inc(int &a,int b){a+=b-mod;a+=a>>31&mod;}
inline void Dec(int &a,int b){a-=b;a+=a>>31&mod;}
inline void Mul(int &a,int b){a=mul(a,b);}
inline int po(int a,int b){
int r=1;for(;b;b>>=1,Mul(a,a))if(b&1)Mul(r,a);return r;
}inline void ex_gcd(int a,int b,int &x,int &y){
if(!b){x=1,y=0;return;}ex_gcd(b,a%b,y,x);y-=a/b*x;
}inline int Inv(int a){static int x,y;ex_gcd(mod,a,y,x);return x+(x>>31&mod);}
inline int MD(ll x){return x>=mod?x%mod:x;}
namespace Sieve{
cs int N=4e5+7;
int mrk[N],pr[N],pc;
void linear_sieves(int lim=1e4){
for(int i=2;i<=lim;++i){
if(!mrk[i])pr[++pc]=i;
for(int re j=1;i*pr[j]<=lim;++j){
mrk[i*pr[j]]=true;
if(i%pr[j]==0)break;
}
}
}
std::mt19937 R(time(0));
inline ll gcd(ll a,ll b){return b?gcd(b,a%b):a;}
inline ll mul(ll a,ll b,ll mod){
if(mod<2e9)return a*b%mod;
return (a*b-(ll)((long double)a/mod*b)*mod+mod)%mod;
}inline ll power(ll a,ll b,ll mod){
ll r=1;a%=mod;
for(;b;b>>=1,a=mul(a,a,mod))
if(b&1)r=mul(r,a,mod);
return r;
}
static cs int p[17]=
{2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59};
bool isprime(ll x){
static std::uniform_int_distribution<int> rnd(0,16);
ll t=x-1,s=0;while(!(t&1))t>>=1,++s;
for(int re tim=0;tim<6;++tim){
ll a=p[rnd(R)]%x;ll b=power(a,t,x);
for(int re j=1;j<=s;++j){
ll k=mul(b,b,x);
if(k==1&&b!=1&&b!=x-1)return false;
b=k;if(b==1)break;
}if(b!=1)return false;
}return true;
}
ll Rho(ll p){
if(p%2==0)return 2;
ll c=(ll)R()%(p-1)+2,x=1,m=1,t;
for(int re k=2;;k<<=1){
ll q=1;
for(int re s=1;s<=k;++s){
x=mul(x,x,p)+c;if(x>=p)x-=p;
q=mul((x-m+p)%p,q,p);
if(!(s&127)&&(t=gcd(p,q))!=1)return t;
}if((t=gcd(p,q))!=1)return t;
m=x;
}assert(0);return -1;
}
}
ll pfc[100];int ord[100],pct;
void get_factor(ll x){
using Sieve::isprime;using Sieve::Rho;if(x==1)return ;
if(isprime(x)){pfc[++pct]=x;return;}
ll p=x;while(p==x)p=Rho(p);ll g=std::__gcd(p,x/p);
get_factor(p/g);get_factor(x/p/g);get_factor(g);
}
void factor(ll x){
using Sieve::pc;using Sieve::pr;
for(int re i=1;i<=pc;++i)
if(x%pr[i]==0){
pfc[++pct]=pr[i];
while(x%pr[i]==0)
x/=pr[i];
}
get_factor(x);
}
cs int N=3e3+7;
int fac[N],_fac[N],inv[N],B[N],coef[N];
inline int C(int n,int m){
return n>=m&&m>=0?mul(fac[n],mul(_fac[m],_fac[n-m])):0;
}
void calc_Poly(int y){
coef[0]=0;
for(int re i=0;i<=y;++i)
coef[y+1-i]=mul(C(y+1,i),B[i]);
for(int re i=0;i<=y+1;++i)
Mul(coef[i],inv[y+1]);
if(y)++coef[y];
}
ll n,nn;int x,y;
int G(int i,int p,int k){
int res=0;
for(int re q=0;q<=k;++q)
Inc(res,po(p,((ll)q*x+(ll)(k-q)*i)%(mod-1)));
for(int re q=0;q<k;++q)
Dec(res,po(p,((ll)q*x+y+(ll)(k-q-1)*i)%(mod-1)));
return res;
}
void Main(){
Sieve::linear_sieves();
fac[0]=fac[1]=1;
inv[0]=inv[1]=1;_fac[0]=_fac[1]=1;
for(int re i=2;i<N;++i){
fac[i]=mul(fac[i-1],i);
inv[i]=mul(inv[mod%i],mod-mod/i);
_fac[i]=mul(_fac[i-1],inv[i]);
}B[0]=1;
for(int re i=1;i+1<N;++i){
for(int re j=0;j<i;++j)
Dec(B[i],mul(C(i+1,j),B[j]));
Mul(B[i],inv[i+1]);
}int T;scanf("%d",&T);
while(T--){
scanf("%lld%d%d",&n,&x,&y);
nn=n;pct=0;factor(n);
std::sort(pfc+1,pfc+pct+1);
pct=std::unique(pfc+1,pfc+pct+1)-pfc-1;
for(int re i=1;i<=pct;++i){
ord[i]=0;
while(n%pfc[i]==0)
++ord[i],n/=pfc[i];
}calc_Poly(y);int ans=0;
for(int re i=0;i<=y+1;++i){
int res=1;
for(int re j=1;j<=pct;++j)
Mul(res,G(i,pfc[j]%mod,ord[j]));
Inc(ans,mul(res,coef[i]));
}cout<<mul(ans,po(MD(nn),y))<<"\n";
}
}
inline void file(){
#ifdef zxyoi
freopen("jzpkil.in","r",stdin);
#endif
}signed main(){file();Main();return 0;}