正题

题目链接:https://www.luogu.com.cn/problem/P4245


题目大意

两个多项式,求它们的乘积模\(p\)。


解题思路

方法好像挺多,我用的是最简单的一种就是,先定一个常数\(sqq\)(一般是\(\sqrt q\)),把一个项的数\(x\)拆成\(k*sqq+r\)。然后把\(F\)的\(k\)丢进\(A\),\(r\)丢进\(B\)。\(G\)的\(k\)丢进\(C\),\(r\)丢进\(D\)。

然后对于\(A*C\)的部分就是\(sqq^2\)的部分,\(A*D+B*C\)就是\(sqq\),\(C*D\)就是\(1\)。这样下来要跑\(7\)次\(\text{FFT}\),很慢但是能过,而且要开\(\text{long double}\)和预处理单位根不然会被卡精度。

有一个比较快的方法是变成两个复数多项式\(E[x]=A[x]+B[x]*i,F[x]=C[x]+D[x]*i\)(其中\(i\)表示\(\sqrt{-1}\))。然后乘起来做一下公式就可以做到\(3\)次\(\text{FFT}\)。

还有一个就是不会被卡精度的\(\text{NTT}\)方法,就是找三个有原根的模数分别跑出来,然后用\(\text{CRT}\)合并,这个跑的次数多,但是因为是\(\text{NTT}\)所以常数和第一个差不多?

时间复杂度都是\(O(n\log n)\)就是常数有不同而已


code

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#define ll long long
using namespace std;
const ll N=4e5+10,sqq=32768;
const long double Pi=acos(-1);
struct complex{
long double x,y;
complex (long double xx=0,long double yy=0)
{x=xx;y=yy;return;}
}A[N],B[N],C[N],D[N];
complex operator+(complex a,complex b)
{return complex(a.x+b.x,a.y+b.y);}
complex operator-(complex a,complex b)
{return complex(a.x-b.x,a.y-b.y);}
complex operator*(complex a,complex b)
{return complex(a.x*b.x-a.y*b.y,a.x*b.y+a.y*b.x);}
ll n,m,p,F[N],G[N],H[N],r[N];
complex w[N];
void FFT(complex *f,ll op,ll n){
for(ll i=0;i<n;i++)
if(i<r[i])swap(f[i],f[r[i]]);
for(ll p=2;p<=n;p<<=1){
ll len=p>>1;
for(ll k=0;k<n;k+=p)
for(ll i=k;i<k+len;i++){
complex tmp=w[n/len*(i-k)];
if(op==-1)tmp.y=-tmp.y;
complex tt=f[i+len]*tmp;
f[i+len]=f[i]-tt;
f[i]=f[i]+tt;
}
}
if(op==-1){
for(ll i=0;i<n;i++)
f[i].x=(ll)(f[i].x/n+0.49);
}
return;
}
void MTT(ll *a,ll *b,ll *c,ll m,ll k){
ll n=1;
while(n<=m+k)n<<=1;
for(ll i=0;i<n;i++)
r[i]=(r[i>>1]>>1)|((i&1)?(n>>1):0);
for(ll len=1;len<n;len<<=1)
for(ll i=0;i<len;i++)
w[n/len*i]=complex(cos(i*Pi/len),sin(i*Pi/len));
for(ll i=0;i<m;i++)
A[i].x=a[i]/sqq,B[i].x=a[i]%sqq;
for(ll i=0;i<k;i++)
C[i].x=b[i]/sqq,D[i].x=b[i]%sqq;
FFT(A,1,n);FFT(B,1,n);FFT(C,1,n);FFT(D,1,n);
complex t1,t2;
for(ll i=0;i<n;i++){
t1=A[i]*C[i];t2=B[i]*D[i];
B[i]=A[i]*D[i]+B[i]*C[i];
A[i]=t1;C[i]=t2;
}
FFT(A,-1,n);FFT(B,-1,n);FFT(C,-1,n);
for(ll i=0;i<n;i++){
(c[i]+=(ll)(A[i].x)*sqq%p*sqq%p)%=p;
(c[i]+=(ll)(B[i].x)*sqq%p)%=p;
(c[i]+=(ll)(C[i].x))%=p;
}
return;
}
signed main()
{
scanf("%lld%lld%lld",&n,&m,&p);
n++;m++;
for(ll i=0;i<n;i++)scanf("%lld",&F[i]);
for(ll i=0;i<m;i++)scanf("%lld",&G[i]);
MTT(F,G,H,n,m);
for(ll i=0;i<n+m-1;i++)
printf("%lld ",(H[i]%p+p)%p);
}

最新文章

  1. Hibernate 继承映射
  2. 对于for循环构成的九宫格里的button,如何满足“有默认选中的一个,并且只能选中一个”?
  3. IOS的MVC
  4. Form_Form Builder本地部署运行的实现(案例)
  5. java 网页页面抓取标题和正文
  6. WinHex分析PE格式(1)
  7. XManager介绍、安装、使用
  8. Samza在YARN上的启动过程 =》 之二 submitApplication
  9. SQLSERVER2000以上 Ad Hoc Distributed Queries的启用与关闭
  10. Lodop错误汇总
  11. oracle学习----去除表中的重复数据
  12. php中CURL技术模拟登陆抓取数据实战,抓取某校教务处学生成绩。
  13. 百度首页top设置
  14. 选项卡 js操作
  15. IIS 7关闭应用程序池自动回收设置
  16. 初学Python(第二课)
  17. asp.net MVC 框架中控制器里使用Newtonsoft.Json对前端传过来的字符串进行解析
  18. python框架django-web层
  19. DEDE暴力破解后台登录页面
  20. 跟随我在oracle学习php(5)

热门文章

  1. DataTable 读取每一行的内容
  2. 如何在github上fork以及同步原作者代码
  3. Spring Boot Mybatis注解:@Mapper和@MapperScan
  4. java Math.random()生成从n到m的随机整数
  5. IO流(File类--递归--过滤器--IO字节流--IO字符流--Properties集合--缓冲流--转换流--序列化流--打印流)
  6. Spring之属性注入
  7. py2neo学习记录
  8. Tensorflow 2.0 深度学习实战 —— 详细介绍损失函数、优化器、激活函数、多层感知机的实现原理
  9. 剖析虚幻渲染体系(11)- RDG
  10. 手撕LRU缓存了解一下