首页 > 其他分享 >【模板】任意模数多项式乘法

【模板】任意模数多项式乘法

时间:2024-02-27 22:37:48浏览次数:17  
标签:__ int 多项式 ll mxn 模数 素数 模板 define

题目描述

给定 \(2\) 个多项式 \(F(x), G(x)\) ,请求出 \(F(x) \times G(x)\)。

系数对 \(p\) 取模,且不保证 \(p\) 可以分解成 \(p = a \cdot 2^k + 1\) 之形式。

题解

可以用快速数论变换NTT算法,关键在于取的那个素数。

由于系数最大为\(10^5 \times 10^{9+9} = 10^{23}\)所以可以用 __int128 来存储,取一个可以表示为\(2^a \times b+1\)的大素数。

用 Python 来找大素数,取两个随机数 \(a\) 和 \(b\) ,然后用 rabinMiller 来判断是否为素数。

找到了一个大素数:\(2^{73} \times 39+1\)

将这个数的欧拉函数分解质因数,从 \(2\) 开始判断,发现 \(17\) 是它的一个原根。

然后就是 __int128 乘法,先转换成 long double 求出两个数相乘除以模数,再转换回 __int128

代码:

#include<bits/stdc++.h>
#define int long long
#define ll __int128
#define mxn 300000
#define ld long double
#define pb push_back
#define mkp make_pair
#define rep(i,a,b) for(int i=a;i<=b;++i)
#define rept(i,a,b) for(int i=a;i<b;++i)
using namespace std;
inline int read(){
	int x=0;char ch=getchar();
	while(!isdigit(ch))ch=getchar();
	while(isdigit(ch))x=(x<<1)+(x<<3)+(ch^48),ch=getchar();
	return x;
}
const ll md=((ll)1<<73)*39+1;
ll mul(ll x,ll y){
	ll a=(ld)x*y/md;
	ll ans=x*y-a*md;
	ans%=md;
	if(ans<0)ans+=md;
	return ans;
}
ll power(ll x,ll y){
	ll ans=1;
	for(;y;y>>=1){
		if(y&1)ans=mul(ans,x);
		x=mul(x,x);
	}
	return ans;
}
inline ll mod(ll a,ll b){
	return mul(a,power(b,md-2));
}
int n,m,k,s,p,rev[mxn];
ll f[mxn],g[mxn];
void ntt(ll *a,int n,int flag){
	rept(i,0,n)if(i<rev[i])swap(a[i],a[rev[i]]);
	for(int h=1;h<n;h<<=1){
		ll x,y,s=power(17,(md-1)/2/h);
		for(int j=0;j<n;j+=h<<1){
			ll w=1;
			for(int k=j;k<j+h;++k){
				x=a[k],y=mul(w,a[k+h]);
				a[k]=(x+y)%md;
				a[k+h]=(x-y+md)%md;
				w=mul(w,s);
			}
		}
	}
	if(flag==-1){
		ll p=power(n,md-2);
		reverse(a+1,a+n);
		rept(i,0,n)a[i]=mul(a[i],p);
	}
}
signed main(){
	n=read(),m=read(),p=read();
	rep(i,0,n)f[i]=read();
	rep(i,0,m)g[i]=read();
	for(k=0,s=1;s<n+m+1;s<<=1,++k);
	rept(i,0,s)rev[i]=(rev[i>>1]>>1)|((i&1)<<(k-1));
	ntt(f,s,1);ntt(g,s,1);
	rept(i,0,s)f[i]=mul(f[i],g[i]);
	ntt(f,s,-1);
	rep(i,0,n+m)printf("%lld ",(int)(f[i]%p));
	return 0;
}

标签:__,int,多项式,ll,mxn,模数,素数,模板,define
From: https://www.cnblogs.com/zifanoi/p/18038557

相关文章

  • 高精度模板!大众福音!
    超级福音!!!高进度模板两大传送门原址传送门(有详细讲解)发现地址传送门废话不多说,直接上代码!#include<bits/stdc++.h>structBigInt{ staticconstintmaxlength=1005; intnum[maxlength],len; voidclean(){ memset(num,0,sizeof(num)); len=1; } BigIn......
  • java 实现根据word模板生成word文件 word转pdf
    最近做项目要求生成word文件及PDF文件,生成word文件时其中内容要根据不同公司提供的内容动态替换里面的值。参考了很多之后选择用word模板生成word文件。其中主要参考:https://www.cnblogs.com/suzan/p/10577738.html 简单的word模板:https://files.cnblogs.com/files/blogs/8095......
  • 类:数据结构(模板)、数据类型(反射)、种类(amount)
    1.析构函数:在GC回收资源时,我们可以在析构函数中做事情; 2.也可以不用new关键字进行创建对象: 使用dynamic,可以直接调用name 3.静态构造器只能初始化静态成员 ......
  • 修改VSCODE默认模板(live template)
    1.问题在使用VSCDOE编写html文件时,对于使用的语言这一块,公司统一要求但是VSCODE默认的是,这就需要我们每次都手改一下,非常麻烦,结合IDEA里面使用livetemplate的经历我就在思考能否修改VSCODE的相关配置文件达到同样的效果呢?首先我找到了这个参考:如何修改vscode模板这里要求我......
  • 【模板】交互题
    Codeforces的交互题有点难以调试,写了一个模板方便本地调试。structOracle{private:staticconstintMAXN=2e5+10;intn;lla[MAXN];llquery_cost;#ifdefLOCALstaticconstboolIS_LOCAL=true;#elsestaticconstboolIS_LOCAL......
  • 多项式模板整理
    约定\(F[i]\)表示\(F(x)\)的\(i\)次项系数。多项式乘法基础详情见多项式乘法入门多项式求逆给出\(n\)次多项式\(F(x)\),求一个多项式\(G(x)\),满足\(F(x)G(x)\equiv1\pmod{x^n}\),\(G(x)\)每个系数对\(998244353\)取模。我们逐一递推,假设已知\(G[1...i-1]\),需......
  • P8436 【模板】边双连通分量
    原题链接题解和点双连通分量不同在于点双联通分量:分量内任意两点之间至少有两条独立路径可走,两条路径所经过的点除了起点和终点都不同边双连通分量:分量内任意两点之间至少有两条独立路径可走,两条路径所经过的边都不同(包括重边)用这个图依然可以解释code#include<bits/stdc++......
  • P8435 【模板】点双连通分量
    原题链接题解唯一能解释的图片,黄色代表会执行入栈操作的点code#include<bits/stdc++.h>usingnamespacestd;intvis[500005]={0};intlow[500005]={0};stack<int>q;vector<int>ans[500005];vector<int>G[500005];intlen=0;intcnt=0;voidss(intnow,intf......
  • P3388 【模板】割点(割顶)
    原题链接题解先说结论对单个图做深度搜索树,对于树的根节点,它要能是割点当且仅当她有至少两个不互通的儿子节点对于树的非叶子非根节点,它要能是割点当且仅当存在儿子节点能去的时间戳最小的节点不小于当前节点的深度搜索序对于叶子节点,不可能成为割点code#include<bits/std......
  • JavaScript语法-字符串模板
    [TOC]##JavaScript模板字符串###代码以下是index.js的部分代码:```onShareAppMessage({const{toName,mainText,fromName}=this.data;debugger;return{title:'叮,您收到一张贺卡~',path:'pages/index/index?toname=${toName}&mai......