http://uoj.ac/problem/34 (题目链接)

题意

  求两个多项式的乘积

Solution

  挂个FFT板子。

细节

  FFT因为要满足$n$是$2$的幂,所以注意数组大小。

代码

// uoj34
#include<algorithm>
#include<iostream>
#include<cstdlib>
#include<cstring>
#include<complex>
#include<cstdio>
#include<cmath>
#define LL long long
#define inf 2147483640
#define Pi acos(-1.0)
#define free(a) freopen(a".in","r",stdin),freopen(a".out","w",stdout);
using namespace std; typedef complex<double> E;
const int maxn=300010;
E a[maxn],b[maxn];
int n,m; namespace FFT {
int rev[maxn],L;
void DFT(E *a,int f) {
for (int i=0;i<n;i++) if (i<rev[i]) swap(a[i],a[rev[i]]);
for (int i=1;i<n;i<<=1) {
E wn(cos(Pi/i),f*sin(Pi/i));
for (int p=i<<1,j=0;j<n;j+=p) {
E w(1,0);
for (int k=0;k<i;k++,w*=wn) {
E x=a[j+k],y=w*a[j+k+i];
a[j+k]=x+y;a[j+k+i]=x-y;
}
}
}
if (f==-1) for (int i=0;i<n;i++) a[i].real()/=n;
}
void main() {
m=n+m;
for (n=1;n<=m;n<<=1) L++; //一定是<=,因为这里的m是最高次幂
for (int i=0;i<n;i++) rev[i]=(rev[i>>1]>>1) | ((i&1)<<(L-1));
DFT(a,1);DFT(b,1);
for (int i=0;i<n;i++) a[i]=a[i]*b[i];
DFT(a,-1);
}
}
int main() {
scanf("%d%d",&n,&m);
for (int i=0,x;i<=n;i++) scanf("%d",&x),a[i]=x;
for (int i=0,x;i<=m;i++) scanf("%d",&x),b[i]=x;
FFT::main();
for (int i=0;i<=m;i++) printf("%d ",(int)(a[i].real()+0.5));
return 0;
}

Solution

  ${NTT}$,适用于对一些形如 ${p=C*2^k+1}$的数取模,且${2^k>n}$(当然也可以将不取模但结果不会超过某个范围视作取模)的多项式乘法问题。

  一些常见的${NTT}$模数:

  ${998244353=119*2^{23}+1}$,原根为${3}$。

  ${1004535809=479*2^{21}+1}$,原根为${3}$。

  ${15*2^{112}+1}$,原根为${1111}$。

  详情请见Xlightgod的博客

代码

// uoj34
#include<algorithm>
#include<iostream>
#include<cstdlib>
#include<cstring>
#include<cstdio>
#include<cmath>
#define LL long long
#define inf 2147483640
#define MOD 998244353
#define Pi acos(-1.0)
#define free(a) freopen(a".in","r",stdin),freopen(a".out","w",stdout);
using namespace std; const int maxn=300010;
int a[maxn],b[maxn],rev[maxn],n,m,L; int power(int a,int b) {
int res=1;
while (b) {
if (b&1) res=1LL*res*a%MOD;
a=1LL*a*a%MOD;b>>=1;
}
return res;
}
void NTT(int *a,int f) {
for (int i=0;i<n;i++) if (i<rev[i]) swap(a[i],a[rev[i]]);
for (int i=1;i<n;i<<=1) {
int gn=power(3,(MOD-1)/(i<<1)); //这里除的是i<<1
for (int p=i<<1,j=0;j<n;j+=p) {
int g=1;
for (int k=0;k<i;k++,g=1LL*g*gn%MOD) {
int x=a[k+j],y=1LL*g*a[k+j+i]%MOD;
a[k+j]=(x+y)%MOD;a[k+j+i]=(x-y+MOD)%MOD;
}
}
}
if (f==-1) {
int ev=power(n,MOD-2);reverse(a+1,a+n); //reverse的是[1,n)
for (int i=0;i<n;i++) a[i]=1LL*a[i]*ev%MOD;
}
}
int main() {
scanf("%d%d",&n,&m);
for (int i=0;i<=n;i++) scanf("%d",&a[i]);
for (int i=0;i<=m;i++) scanf("%d",&b[i]);
m=n+m;
for (n=1;n<=m;n<<=1) L++;
for (int i=0;i<n;i++) rev[i]=(rev[i>>1]>>1) | ((i&1)<<(L-1));
NTT(a,1);NTT(b,1);
for (int i=0;i<n;i++) a[i]=1LL*a[i]*b[i]%MOD;
NTT(a,-1);
for (int i=0;i<=m;i++) printf("%d ",a[i]);
return 0;
}

Solution3

  听说还有任意模数的${NTT}$,比如说对${1000000007}$取模,那么这显然是不能直接${NTT}$的,直接${FFT}$转成整型取模的时候又会爆LL。我用的是毛爷爷的做法,把一个数${x}$拆成${x=a*M+b}$,${M}$是模数的算术平方根。这样就能避免爆LL了。

  具体见上面那个链接:Xlightgod。

代码

// uoj34
#include<algorithm>
#include<iostream>
#include<cstdlib>
#include<cstring>
#include<complex>
#include<cstdio>
#include<cmath>
#include<queue>
#define LL long long
#define inf 1ll<<60
#define MOD 1000000007
#define M 32768
#define Pi acos(-1.0)
#define free(a) freopen(a".in","r",stdin),freopen(a".out","w",stdout);
using namespace std; typedef complex<double> E;
const int maxn=300010;
E a[maxn],b[maxn],c[maxn],d[maxn],A[maxn],B[maxn],C[maxn];
int n,m,L,rev[maxn]; void FFT(E *a,int f) {
for (int i=0;i<n;i++) if (rev[i]>i) swap(a[i],a[rev[i]]);
for (int i=1;i<n;i<<=1) {
E wn(cos(Pi/i),f*sin(Pi/i));
for (int p=i<<1,j=0;j<n;j+=p) {
E w(1,0);
for (int k=0;k<i;k++,w*=wn) {
E x=a[j+k],y=w*a[j+k+i];
a[j+k]=x+y;a[j+k+i]=x-y;
}
}
}
if (f==-1) for (int i=0;i<n;i++) a[i].real()=a[i].real()/n+0.5; //这里的0.5一定要除了再加上去
} int main() {
scanf("%d%d",&n,&m);
for (int x,i=0;i<=n;i++) {
scanf("%d",&x);
a[i]=x>>15;b[i]=x&(M-1);
}
for (int x,i=0;i<=m;i++) {
scanf("%d",&x);
c[i]=x>>15;d[i]=x&(M-1);
}
m=n+m;
for (n=1,L=-1;n<=m;n<<=1) L++;
for (int i=0;i<n;i++) rev[i]=(rev[i>>1]>>1) | ((i&1)<<L);
FFT(a,1);FFT(b,1);FFT(c,1);FFT(d,1);
for (int i=0;i<n;i++) {
A[i]=a[i]*c[i];
B[i]=a[i]*d[i]+b[i]*c[i];
C[i]=b[i]*d[i];
}
FFT(A,-1);FFT(B,-1);FFT(C,-1);
for (int i=0;i<=m;i++) {
LL x=(LL)A[i].real()%MOD,y=(LL)B[i].real()%MOD,z=(LL)C[i].real()%MOD;
printf("%lld ",((x<<30)+(y<<15)+z)%MOD);
}
return 0;
}

  

【uoj34】 多项式乘法的更多相关文章

  1. UOJ34 多项式乘法(NTT)

    本文版权归ljh2000和博客园共有,欢迎转载,但须保留此声明,并给出原文链接,谢谢合作. 本文作者:ljh2000 作者博客:http://www.cnblogs.com/ljh2000-jump/ ...

  2. UOJ34 多项式乘法

    本文版权归ljh2000和博客园共有,欢迎转载,但须保留此声明,并给出原文链接,谢谢合作. 本文作者:ljh2000作者博客:http://www.cnblogs.com/ljh2000-jump/转 ...

  3. UOJ34 多项式乘法(非递归版)

    本文版权归ljh2000和博客园共有,欢迎转载,但须保留此声明,并给出原文链接,谢谢合作. 本文作者:ljh2000 作者博客:http://www.cnblogs.com/ljh2000-jump/ ...

  4. 【Uoj34】多项式乘法(NTT,FFT)

    [Uoj34]多项式乘法(NTT,FFT) 题面 uoj 题解 首先多项式乘法用\(FFT\)是一个很久很久以前就写过的东西 直接贴一下代码吧.. #include<iostream> # ...

  5. [UOJ#34]多项式乘法

    [UOJ#34]多项式乘法 试题描述 这是一道模板题. 给你两个多项式,请输出乘起来后的多项式. 输入 第一行两个整数 n 和 m,分别表示两个多项式的次数. 第二行 n+1 个整数,分别表示第一个多 ...

  6. [笔记]ACM笔记 - 利用FFT求卷积(求多项式乘法)

    卷积 给定向量:, 向量和: 数量积(内积.点积): 卷积:,其中 例如: 卷积的最典型的应用就是多项式乘法(多项式乘法就是求卷积).以下就用多项式乘法来描述.举例卷积与DFT. 关于多项式 对于多项 ...

  7. FFT模板(多项式乘法)

    FFT模板(多项式乘法) 标签: FFT 扯淡 一晚上都用来捣鼓这个东西了...... 这里贴一位神犇的博客,我认为讲的比较清楚了.(刚好适合我这种复数都没学的) http://blog.csdn.n ...

  8. 【learning】多项式乘法&fft

    [吐槽] 以前一直觉得这个东西十分高端完全不会qwq 但是向lyy.yxq.yww.dtz等dalao们学习之后发现这个东西的代码实现其实极其简洁 于是趁着还没有忘记赶紧来写一篇博 (说起来这篇东西的 ...

  9. 多项式乘法(FFT)学习笔记

    ------------------------------------------本文只探讨多项式乘法(FFT)在信息学中的应用如有错误或不明欢迎指出或提问,在此不胜感激 多项式 1.系数表示法  ...

随机推荐

  1. Delphi DBGrid类控件定位到某一行,并更改为选中状态。

    Delphi中,可以使用数据集控件提供的 Locate 成员方法快速定位至某条记录, 然后通过清除数据集控件的选中状态,并重新赋值达到我们的目的. grDirectory.DataSource.Dat ...

  2. Flutter - JSON to Dart,一个json转dart实体的网站

    如你所见,一个json转dart实体的网站,https://javiercbk.github.io/json_to_dart/

  3. 20155233 《网络对抗》Exp4 恶意代码分析

    使用schtasks指令监控系统运行 先在C盘目录下建立一个netstatlog.bat文件,用来将记录的联网结果格式化输出到netstatlog.txt文件中,netstatlog.bat内容为: ...

  4. linux下使用软连接之案例二

           在笔者的上一篇文章介绍过怎么通过linux的软连接在不修改上传代码的情况下,将上传到项目路径下的图片改为上传到项目外面,防止重新部署后图片被删除了.同时还可以直接通过类似访问静态资源的方 ...

  5. 复选框、单选框 jquery判断是否选中Demo

    <%@ Page Language="C#" AutoEventWireup="true" CodeBehind="eachcheckbox.a ...

  6. Luogu P2055 [ZJOI2009]假期的宿舍

    一道网络有关的问题,还是一句话 网络流重在建模! 这里主要讲两种算法. 1.二分图匹配: 分析题意,我们可以知道题目要求是让所有留在学校的人都能有床睡 而 所有留在学校的人=本校不回家的人+外校的人: ...

  7. Asp.Net_Ajax调用WebService返回Json前台获取循环解析

    利用JQuery的$.ajax()可以很方便的调用 asp.net的后台方法.但往往从后台返回的json字符串不能够正确解析,究其原因,是因为没有对返回的json数据做进一步的加工.其实,这里只需 要 ...

  8. PAT甲题题解-1035. Password (20)-水

    题意:给n个用户名和密码,把密码中的1改为@,0改为%,l改为L,O改为o. 让你输出需要修改密码的用户名个数,以及对应的用户名和密码,按输入的顺序.如果没有用户需要修改,则输出对应的语句,注意单复数 ...

  9. PAT甲题题解-1049. Counting Ones-数学问题

    n位数,总共有0~10^n-1共计10^n个数那么所有数出现的总次数变为n*(10^n)个数1出现的次数便是十分之一,所以n位数中,1出现的次数为n*10^(n-1)知道这一个后,接下来就方便求了. ...

  10. Todo&Rocket

    Todo是怎么实现的? 前面两篇博客分别介绍了MVC和Backbone.js的逻辑,但是实战获真知,在来一篇来显示下Todo是怎么通过Backbone.js连接起来的. 忽略掉所有的代码,我们只是打开 ...