P4464 JZPKIL 题解

又是一道独立(基本上是)做出的黑,好耶!注:下文为了简洁除法用 / 代替分数。


前置知识:伯努利数求自然数幂和。

伯努利数:B0=1,i=0n(n+1i)Bi=0(n1),于是可以 O(n2) 预处理前 n 个伯努利数。

有结论:i=1n1ik=1k+1i=1k+1(k+1i)Bk+1ini

于是 sk(n)=i=1nik=1k+1i=1k+1(k+1i)Bk+1ini+nksk 是一个关于 nk+1 次多项式。于是我们可以 O(N2) 预处理出 kNsk 的每项系数。


推式子:

i=1n(i,n)x((ni)/(i,n))y=nyi=1n(i,n)xyiy=nydndxyi=1niy[(i,n)=d]=nydndxyi=1n/d(id)y[(i,n/d)=1]=nydndxi=1n/diyD(i,n/d)μ(D)=nydndxDn/dμ(D)Dyi=1n/Ddiy=nyDnμ(D)Dydn/D(Dd/D)xs(n/dD)=nyDnμ(D)DyxDdn(Dd)xs(n/Dd)


其中 s(x)=i=1xiy,就是自然数幂和。接下来我们套路性的令 T=Dd

nyDnμ(D)DyxDdn(Dd)xs(n/Dd)=nyTnTxs(n/T)DTμ(D)Dyx

我们可以把 s 用前置知识拆成多项式,令 s(n)=i=1y+1aini,则

nyTnTxs(n/T)DTμ(D)Dyx=nyi=1y+1aiTnTx(n/T)iDTμ(D)Dyx=nyi=1y+1ainiTnTxiDTμ(D)Dyx


注意到 aini 后面很积性啊,有结论:若 f 为积性函数,n 质因数分解为:n=i=1kpiαi,则:

g(n)=dnf(d)=i=1k(j=0αif(pij)),也是个积性。

考虑素数幂处的值(可以用 FFT 中的点值来理解下面)

f(n)=dnμ(d)dyx 为积性函数,则对每个 n 的素数幂因子,f(pα) 是可以快速预处理的。

TnTxiDTμ(D)Dyx=TnTxif(T)=i=1k(j=0αipij(xi)f(pij))

这就很好算啦!先 Pollard-Rho 分解质因子,而后枚举原式中的 i,对于每个 n 的素因子计算后面那坨即可,注意 f 不受原式 i 的影响,于是只用预处理一次即可,当然这是常数优化。

复杂度:O(T(n1/4+yw(n)logn)),其中 w(n)n 的质因子个数,为 O(logn) 级别。

几乎没怎么优化就跑得很快,目前谷 rk3。代码:

#include<bits/stdc++.h>
#define P pair<int,int>
#define fi first
#define se second
#define LL long long
#define bll __int128
#define fr(x) freopen(#x".in","r",stdin);freopen(#x".out","w",stdout);
using namespace std;
mt19937 rnd(time(0));
const int N=3e3+5,M=N-5,mod=1e9+7;
int T,B[N],jc[N],inv[N],I[N],a[N][N],x,y,pw,ans;LL n;
inline int md(int x){return x>=mod?x-mod:x;}
inline int ksm(int x,int p){int s=1;for(;p;(p&1)&&(s=1ll*s*x%mod),x=1ll*x*x%mod,p>>=1);return s;}
inline int C(int n,int m){return 1ll*jc[n]*inv[m]%mod*inv[n-m]%mod;}
int t,c[95],f[95][95],g[95][95];LL PP[95];
namespace PRHO
{
	#define mytz __builtin_ctzll
	#define Abs(x) ((x)>0?(x):-(x))
	inline LL gcd(LL a,LL b)
	{
		LL az=mytz(a),bz=mytz(b),z=min(az,bz),diff;b>>=bz;
		while(a) a>>=az,diff=a-b,az=mytz(diff),b=min(a,b),a=Abs(diff);return b<<z;
	}
	inline LL ksm(LL x,LL p,LL mod){LL s=1;for(;p;(p&1)&&(s=(bll)s*x%mod),x=(bll)x*x%mod,p>>=1);return s;}
	const LL pr[]={2,3,5,7,11,13,17,19,23,29,31,37};
	inline bool check(LL a,LL p)
	{
		LL d=a-1,t=0;while(~d&1) d>>=1,t++;LL now=ksm(p,d,a);
		if(now==1||now==0||now==a-1) return 1;
		for(int i=0;i<t;i++)
		{
			now=(bll)now*now%a;
			if(now==1) return 0;
			if(now==a-1&&i!=t-1) return 1;
		}
		return 0;
	}
	inline bool pd(LL x)
	{
		if(x==1) return 0;
		for(LL i:pr)
		{
			if(x==i) return 1;
			if(x%i==0||!check(x,i)) return 0;
		}return 1;
	}
	#define f(x,c,n) (((bll)(x)*(x)+(c))%(n))
	inline LL Find(LL x)
	{
		LL t1=1ll*rnd()*rnd()%(x-1)+1,c=1ll*rnd()*rnd()%(x-1)+1,t2=f(t1,c,x),d,mul=1;
		for(int i=1;;i<<=1,t1=t2,mul=1)
		{
			for(int j=1;j<=i;j++)
			{
				t2=f(t2,c,x);
				mul=(bll)mul*Abs(t1-t2)%x;
				if(j%127==0){d=gcd(mul,x);if(d>1) return d;}
			}d=gcd(mul,x);
			if(d>1) return d;
		}
	}
	void po(LL x)
	{
		if(x==1) return;
		if(pd(x)) return PP[++t]=x,void();LL num=Find(x);
		while(x%num==0) x/=num;po(x),po(num);
	}
	inline void bk(LL x)
	{
		t=c[1]=0;po(x);sort(PP+1,PP+1+t);t=unique(PP+1,PP+1+t)-PP-1;
		for(int i=1;i<=t;c[++i]=0) while(x%PP[i]==0) c[i]++,x/=PP[i];
	}
}using PRHO::bk;
inline void sol1()
{
	for(int i=1;i<=t;i++) PP[i]%=mod;
	for(int i=1;i<=t;i++)
	{
		int w=ksm(PP[i],pw);
		for(int j=f[i][0]=1,s=w;j<=c[i];j++,s=1ll*s*w%mod)
			f[i][j]=f[i][j-1],(j<=1)&&(f[i][j]=md(f[i][j]-s+mod));
	}
}
inline int sol2(int i)
{
	int PW=(x-i+mod-1)%(mod-1),ans=1;
	for(int i=1,w=ksm(PP[1],PW);i<=t;w=ksm(PP[++i],PW))
		for(int j=0,s=1;j<=c[i];j++,s=1ll*s*w%mod) g[i][j]=1ll*f[i][j]*s%mod;
	for(int i=1,s=0;i<=t;i++,ans=1ll*ans*s%mod,s=0) for(int j=0;j<=c[i];j++) s=md(s+g[i][j]);
	return ans;
}
int main()
{
	ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);cin>>T;
	for(int i=jc[0]=1;i<=M+1;i++) jc[i]=1ll*jc[i-1]*i%mod;
	inv[M+1]=ksm(jc[M+1],mod-2);for(int i=M;i>=0;i--) inv[i]=1ll*inv[i+1]*(i+1)%mod;
	I[1]=1;for(int i=2;i<=M+1;i++) I[i]=mod-1ll*(mod/i)*I[mod%i]%mod;
	for(int i=B[0]=1;i<=M;i++)
	{
		for(int j=0;j<i;j++) B[i]=(B[i]+1ll*B[j]*C(i+1,j))%mod;
		B[i]=md(mod-1ll*I[i+1]*B[i]%mod);
	}
	for(int i=0;i<=M;a[i][i]++,i++) for(int j=0;j<=i;j++) a[i][i+1-j]=1ll*B[j]*C(i+1,j)%mod*I[i+1]%mod;
	while(T--)
	{
		cin>>n>>x>>y;bk(n);pw=(y-x+mod-1)%(mod-1);sol1();ans=0;
		for(int i=1;i<=y+1;i++) ans=(ans+1ll*a[y][i]*ksm(n%mod,i)%mod*sol2(i))%mod;
		cout<<(1ll*ans*ksm(n%mod,y)%mod)<<"\n";
	}
	return 0;
}
posted @   HaHeHyt  阅读(68)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】
点击右上角即可分享
微信分享提示
主题色彩
主题色彩