大常数选手求调TLE50pts三模数NTT求逆
查看原帖
大常数选手求调TLE50pts三模数NTT求逆
444040
Echoternity楼主2023/1/15 10:42

应该没写错吧,Sub1全过。

// ----- Eternally question-----
// Problem: P4239 任意模数多项式乘法逆
// Contest: Luogu
// URL: https://www.luogu.com.cn/problem/P4239
// Memory Limit: 125 MB
// Time Limit: 3000 ms
// Written by: Eternity
// Time: 2023-01-15 09:42:50
// ----- Endless solution-------

#include<bits/stdc++.h>
#define re register
typedef __int128_t ll;
template<class T>
inline void read(T &x)
{
	x=0;
	char ch=getchar(),t=0;
	while(ch<'0'||ch>'9') t|=ch=='-',ch=getchar();
	while(ch>='0'&&ch<='9') x=(x<<3)+(x<<1)+(ch^48),ch=getchar();
	if(t) x=-x;
}
template<class T,class ...T1>
inline void read(T &x,T1 &...x1){ read(x),read(x1...); }
template<class T>
inline void write(T x)
{
	if(x<0) putchar('-'),x=-x;
	if(x>9) write(x/10);
	putchar(x%10+'0');
}
template<>
inline void write(bool x){ putchar(x?'1':'0'); }
template<>
inline void write(char c){ putchar(c); }
template<>
inline void write(char *s){ while(*s!='\0') putchar(*s++); }
template<>
inline void write(const char *s){ while(*s!='\0') putchar(*s++); }
template<class T,class ...T1>
inline void write(T x,T1 ...x1){ write(x),write(x1...); }
template<class T>
inline bool checkMax(T &x,T y){ return x<y?x=y,1:0; }
template<class T>
inline bool checkMin(T &x,T y){ return x>y?x=y,1:0; }
const int MAXN=4e5+10;
const int Mod=1e9+7,G=3;
const ll P[]={0,469762049,998244353,1004535809};
int N;
ll f[MAXN],g[MAXN];
inline ll qPow(ll a,ll b,ll p)
{
	ll res=1;
	while(b)
	{
		if(b&1) res=res*a%p;
		a=a*a%p;b>>=1;
	}
	return res;
}
int Rev[MAXN],Bit,Tot;
inline void reverse(int n)
{
	Bit=0;
	while((1<<Bit)<=n) ++Bit;
	Tot=1<<Bit;
	for(int i=0;i<Tot;++i) Rev[i]=(Rev[i>>1]>>1)|((i&1)<<(Bit-1));
}
inline void NTT(ll a[],int n,ll p,int inv)
{
	for(int i=0;i<n;++i)
		if(i<Rev[i]) std::swap(a[i],a[Rev[i]]);
	ll invG=qPow(G,p-2,p);
	for(int mid=1;mid<n;mid<<=1)
	{
		ll w1=qPow(inv==1?G:invG,(p-1)/(mid<<1),p);
		for(int i=0;i<n;i+=mid*2)
		{
			ll wk=1;
			for(int j=0;j<mid;++j,wk=wk*w1%p)
			{
				ll x=a[i+j],y=a[i+j+mid]*wk%p;
				a[i+j]=(x+y)%p,a[i+j+mid]=(x-y+p)%p;
			}
		}
	}
	if(inv==-1)
	{
		ll iv=qPow(n,p-2,p);
		for(int i=0;i<n;++i) a[i]=a[i]*iv%p;
	}
}
ll a[MAXN],b[MAXN];
inline void Mul(ll f[],ll g[],int n,ll p,ll ans[])
{
	// reverse(n);
	for(int i=0;i<n;++i) a[i]=f[i],b[i]=g[i];
	for(int i=n;i<Tot;++i) a[i]=b[i]=0;
	NTT(a,Tot,p,1),NTT(b,Tot,p,1);
	for(int i=0;i<Tot;++i) ans[i]=a[i]*b[i]%p;
	NTT(ans,Tot,p,-1);
	for(int i=n;i<Tot;++i) ans[i]=0;
}
ll Ps=P[1]*P[2];
ll iv1=qPow(P[2]%P[1],P[1]-2,P[1]),iv2=qPow(P[1]%P[2],P[2]-2,P[2]),iv3=qPow(Ps%P[3],P[3]-2,P[3]);
inline ll crt(ll a,ll b,ll c)
{
	ll x=(P[2]*a%Ps*iv1%Ps+P[1]*b%Ps*iv2%Ps)%Ps;
	ll s=(c-x%P[3]+P[3])%P[3]*iv3%P[3];
	return (s%Mod*(Ps%Mod)%Mod+x%Mod)%Mod;
}
inline void MTT(ll f[],ll g[],int n,ll res[])
{
	static ll ans[4][MAXN];
	for(int k=1;k<=3;++k) Mul(f,g,n,P[k],ans[k]);
	for(int i=0;i<n;++i)
	{
		ll ct=crt(ans[1][i],ans[2][i],ans[3][i]);
		for(int k=1;k<=3;++k) ans[k][i]=(Mod-ct)%Mod;
	}
	*ans[1]=*ans[2]=*ans[3]=1;
	for(int k=1;k<=3;++k) Mul(ans[k],g,n,P[k],ans[k]);
	for(int i=0;i<n;++i) res[i]=crt(ans[1][i],ans[2][i],ans[3][i]);
}
void inverse(int n,ll f[],ll g[])
{
	if(n==1) return *g=qPow(*f,Mod-2,Mod),void();
	inverse((n+1)>>1,f,g);
	reverse(n+N);
	MTT(f,g,n,g);
}
int main()
{
	// freopen(".in","r",stdin);
	// freopen(".out","w",stdout);
	read(N);
	for(int i=0;i<N;++i) read(f[i]),f[i]%=Mod;
	inverse(N,f,g);
	for(int i=0;i<N;++i) write(g[i],' ');
	return 0;
}
/*

*/
2023/1/15 10:42
加载中...