快速阶乘算法

快速阶乘算法求:n! mod p\largen!\text{mod}pn! mod p时间复杂度:Θ(nlog⁡n)\Theta(\sqrtn\logn)Θ(n​logn)模板题:P5282【模板】快速阶乘算法参考:P5282【模板】快速阶乘算法(多项式运算+拉格朗日插值+倍增)//minamoto#include<bits/stdc++.h>#defineRregister#definelllonglong#defin

大家好,又见面了,我是你们的朋友全栈君。

求: n !  mod  p \large n! \text{ mod } p n! mod p
时间复杂度: Θ ( n log ⁡ n ) \Theta(\sqrt n \log n) Θ(n
​
logn)

模板题:P5282 【模板】快速阶乘算法
参考:P5282 【模板】快速阶乘算法(多项式运算+拉格朗日插值+倍增)

//minamoto
#include<bits/stdc++.h>
#define R register
#define ll long long
#define fp(i,a,b) for(R int i=(a),I=(b)+1;i<I;++i)
#define fd(i,a,b) for(R int i=(a),I=(b)-1;i>I;--i)
#define go(u) for(int i=head[u],v=e[i].v;i;i=e[i].nx,v=e[i].v)
using namespace std;

struct Fast_fac {
	static const int N=(1<<17)+5;int P;
	inline int add(R int x,R int y){return 0ll+x+y>=P?0ll+x+y-P:x+y;}
	inline int dec(R int x,R int y){return x-y<0?x-y+P:x-y;}
	inline int mul(R int x,R int y){return 1ll*x*y-1ll*x*y/P*P;}
	int ksm(R int x,R int y){
		R int res=1;
		for(;y;y>>=1,x=mul(x,x))(y&1)?res=mul(res,x):0;
		return res;
	}
	const double Pi=acos(-1.0);
	struct cp{
		double x,y;
		inline cp(){}
		inline cp(R double xx,R double yy):x(xx),y(yy){}
		inline cp operator +(const cp &b)const{return cp(x+b.x,y+b.y);}
		inline cp operator -(const cp &b)const{return cp(x-b.x,y-b.y);}
		inline cp operator *(const cp &b)const{return cp(x*b.x-y*b.y,x*b.y+y*b.x);}
		inline cp operator *(const double &b)const{return cp(x*b,y*b);}
		inline cp operator ~()const{return cp(x,-y);}
	}w[2][N];
	int r[21][N],ifac[N],lg[N],inv[N];double iv[21];
	void Pre(){
		iv[0]=1;
		fp(d,1,17){
			fp(i,0,(1<<d)-1)r[d][i]=(r[d][i>>1]>>1)|((i&1)<<(d-1));
			lg[1<<d]=d,iv[d]=iv[d-1]*0.5;
		}
		inv[0]=inv[1]=ifac[0]=ifac[1]=1;
		fp(i,2,131072)inv[i]=mul(P-P/i,inv[P%i]),ifac[i]=mul(ifac[i-1],inv[i]);
		for(R int i=1,d=0;i<131072;i<<=1,++d)fp(k,0,i-1)
			w[1][i+k]=cp(cos(Pi*k*iv[d]),sin(Pi*k*iv[d])),
			w[0][i+k]=cp(cos(Pi*k*iv[d]),-sin(Pi*k*iv[d]));
	}
	int lim,d;
	void FFT(cp *A,int ty){
		fp(i,0,lim-1)if(i<r[d][i])swap(A[i],A[r[d][i]]);
		cp t;
		for(R int mid=1;mid<lim;mid<<=1)
			for(R int j=0;j<lim;j+=(mid<<1))
				fp(k,0,mid-1)
					A[j+k+mid]=A[j+k]-(t=w[ty][mid+k]*A[j+k+mid]),
					A[j+k]=A[j+k]+t;
		if(!ty)fp(i,0,lim-1)A[i]=A[i]*iv[d];
	}
	void MTT(int *a,int *b,int len,int *c){
	    static cp f[N],g[N],p[N],q[N];
	    lim=len,d=lg[lim];
	    fp(i,0,len-1)f[i]=cp(a[i]>>16,a[i]&65535),g[i]=cp(b[i]>>16,b[i]&65535);
	    fp(i,len,lim-1)f[i]=g[i]=cp(0,0);
	    FFT(f,1),FFT(g,1);
	    fp(i,0,lim-1){
	        cp t,f0,f1,g0,g1;
	        t=~f[i?lim-i:0],f0=(f[i]-t)*cp(0,-0.5),f1=(f[i]+t)*0.5;
	        t=~g[i?lim-i:0],g0=(g[i]-t)*cp(0,-0.5),g1=(g[i]+t)*0.5;
	        p[i]=f1*g1,q[i]=f1*g0+f0*g1+f0*g0*cp(0,1);
	    }
	    FFT(p,0),FFT(q,0);
	    fp(i,0,lim-1)c[i]=((((ll)(p[i].x+0.5)%P<<16)%P<<16)+((ll)(q[i].x+0.5)<<16)+((ll)(q[i].y+0.5)))%P;
	}
	void calc(int *a,int *b,int n,int k){
		static int f[N],g[N],h[N],sum[N],isum[N];
		int len=1;while(len<=n+n)len<<=1;
		fp(i,0,n)f[i]=mul(a[i],mul(ifac[i],ifac[n-i]));
		for(R int i=n-1;i>=0;i-=2)f[i]=P-f[i];
		int t=dec(k,n);
		fp(i,0,n+n)g[i]=add(i,t);
		sum[0]=g[0];fp(i,1,n+n)sum[i]=mul(sum[i-1],g[i]);
		isum[n+n]=ksm(sum[n+n],P-2);
		fd(i,n+n,1)isum[i-1]=mul(isum[i],g[i]);
		fp(i,1,n+n)g[i]=mul(isum[i],sum[i-1]);g[0]=isum[0];
		fp(i,n+1,len-1)f[i]=0;fp(i,n+n+1,len-1)g[i]=0;
		
		MTT(f,g,len,h);
		int res=1,p1=k-n,p2=k;
		fp(i,p1,p2)res=1ll*res*i%P;
		res=dec(res,0);
		
		fp(i,0,n)g[i]=(0ll+P+p1+i)%P;
		sum[0]=g[0];fp(i,1,n)sum[i]=mul(sum[i-1],g[i]);
		isum[n]=ksm(sum[n],P-2);
		fd(i,n,1)isum[i-1]=mul(isum[i],g[i]);
		fp(i,1,n)g[i]=mul(isum[i],sum[i-1]);g[0]=isum[0];
		
		for(R int i=0;i<=n;p2=add(p2,1),++i)
			b[i]=mul(h[i+n],res),res=mul(res,mul(g[i],p2+1));
	}
	int solve(int bl){
		static int a[N],b[N],c[N];
		int s=0;for(int p=bl;p;p>>=1)++s;a[0]=1,--s;
		int qwq=ksm(bl,P-2);
		for(int p=0;s>=0;--s){
			if(p){
				calc(a,b,p,p+1);
				fp(i,0,p)a[p+i+1]=b[i];a[p<<1|1]=0;
				calc(a,b,p<<1,mul(p,qwq));
				p<<=1;fp(i,0,p)a[i]=mul(a[i],b[i]);
			}
			if(bl>>s&1){
				fp(i,0,p)a[i]=mul(a[i],(1ll*bl*i+p+1)%P);
				p|=1,a[p]=1;
				fp(i,1,p)a[p]=mul(a[p],(1ll*bl*p+i)%P);
			}
		}
		int res=1;
		fp(i,0,bl-1)res=mul(res,a[i]);
		return res;
	}
	int GetFac(int n){
		int s=sqrt(n),res=solve(s);
		fp(i,s*s+1,n)res=mul(res,i);
		return res;
	}
	int Fac(int n){
		if(n>P-1-n){
			int res=ksm(GetFac(P-1-n),P-2);
			return (P-1-n)&1?res:P-res;
		}
		return GetFac(n);
	}
} sol;

int main(){
	int n, P, T;
	scanf("%d", &T);
	while(T--) {
		scanf("%d%d", &n, &P);
		sol.P = P, sol.Pre();
		printf("%d\n", sol.Fac(n));
	} 
}
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/163986.html原文链接:https://javaforall.net

赞 (0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • kotlin相比于java的好处和坏处_kotlin和java

    kotlin相比于java的好处和坏处_kotlin和java什么是Kotlin?什么是Java?主要区别:Kotlin的特点Java的特点Kotlin的历史JAVA的历史Kotlin和Java的区别Kotlin的优势Java的优势Kotlin的缺点Java的缺点哪个更好?

    2022年10月22日
  • Python的pywifi模块

    Python的pywifi模块想蹭❤️小姐姐的热点❤️被拒后,我用❤️Python来暴力激活成功教程了WiFi的密码❤️文章目录想蹭❤️小姐姐的热点❤️被拒后,我用❤️Python来暴力激活成功教程了WiFi的密码❤️一、起因背景二、需求分析三、代码实现1、生成密码本2、利用密码本进行自动化的测试3、结果展示四、后续总结一、起因背景这天博主和曾经的一个小姐姐同学凑巧同时坐在了同一辆长途客车上,恰谈之后才了解到原来这位小姐姐家里挺富裕的,居然,开通了无限的流量使用权限,博主心想,既然是老同学了,借用一下这个无限的流量应该是没什么问题吧,反正是

    2022年7月27日
  • 详解List的toArray()方法和toArray(T[] a)方法

    详解List的toArray()方法和toArray(T[] a)方法这两个方法都是将列表List中的元素转导出为数组,不同的是,toArray()方法导出的是Object类型数组,而toArray[T[]a]方法导出的是指定类型的数组。下面是两个方法的申明及说明,摘自Java8的API文档。toArray()方法的分析Object[]toArray()Returnsanarraycontainingalloftheelementsinthislistinpropersequence(fromfirsttolastelem

    2022年5月14日
  • Java socket接收出现中文乱码[通俗易懂]

    Java socket接收出现中文乱码[通俗易懂]今天写Tcp,发现中文乱码的问题,百度了一下,发现这篇文章,开头两句话就解决了我的问题,读完受益匪浅啊,呵呵,收藏先。尊重版权:原文地址:http://hi.baidu.com/linjk03/blog/item/10023afad8303cd9b48f311a.htmlin=newBufferedReader(newInputStreamReader(socket.get

    2022年7月8日
  • Springboot-软件授权License

    Springboot-软件授权License在我们做系统级框架的时候,我们要一定程度上考虑系统的使用版权,不能随便一个人拿去在任何环境都能用,所以我们需要给我们系统做一个授权认证机制,只有上传了我们下发的lic文件并验证通过,才能正常使用。1、Smart-license简介smart-license是一款用于安全加固的开源项目。主要服务于非开源产品、商业软件、具备试用功能的付费软件等,为软件提供授权制的使用方式。1.License,通过smart-license生成的授权文件,导入至要授权使用的软件产品中。2.源数据,需要进行L

    2022年7月26日
  • 玩玩webgame开发(2):人物移动与战争迷雾实现

    玩玩webgame开发(2):人物移动与战争迷雾实现惯例,先上下效果图片:[img]/upload/attachment/47613/3b8e0d31-b9cc-3272-abbb-0941300a68ef.png[/img]在上一篇玩玩webgame开发(1)大概给出了jquery方式的地图实现,最近又做了一些改进,加进了更多元素。代码全部改成jquery插件的方式。有机会做专门的介绍。这次的主题主要是地图上面人物的移动以及战…

    2022年5月25日

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号