FFT/NTT模板 既 HDU1402 A * B Problem Plus
@(学习笔记)[FFT, NTT]
Problem Description
Calculate A * B.
Input
Each line will contain two integers A and B. Process to end of file.
Note: the length of each integer will not exceed 50000.
Output
For each case, output A * B in one line.
Sample Input
1
2
1000
2
Sample Output
2
2000
Solution
FFT和NTT都是可以的.
FFT: 没有特别要求.
const int N = 1 << 17;
char str1[N], str2[N];
#include<cstdio>
#include<cstring>
int len1, len2;
struct complex
{
double real, imag;
inline complex(){}
inline complex(double _real, double _imag)
{
real = _real, imag = _imag;
}
inline friend complex operator *(complex a, complex b)
{
return complex(a.real * b.real - a.imag * b.imag, a.imag * b.real + b.imag * a.real);
}
inline friend complex operator +(complex a, complex b)
{
return complex(a.real + b.real, a.imag + b.imag);
}
inline friend complex operator -(complex a, complex b)
{
return complex(a.real - b.real, a.imag - b.imag);
}
}a[N << 1], b[N << 1];
#include<algorithm>
int len;
int rev[N << 1];
inline void prepare(complex *a, complex *b)
{
int mx = std::max(len1, len2) << 1;
len = 1;
int bit = 0;
while(len < mx)
len <<= 1, ++ bit;
rev[0] = 0;
for(int i = 1; i < len; ++ i)
rev[i] = rev[i >> 1] >> 1 | (i & 1) << (bit - 1);
}
inline void reverse(complex *a)
{
for(int i = 0; i < len; ++ i)
if(rev[i] < i)
std::swap(a[i], a[rev[i]]);
}
#include<cmath>
const double PI = acos(-1.0);
inline void fft(complex *a, int opt)
{
reverse(a);
for(int i = 2; i <= len; i <<= 1)
{
complex omega_n = complex(cos(2.0 * PI * (double)opt / (double)i), sin(2.0 * PI * (double)opt / (double)i));
for(int j = 0; j < len; j += i)
{
complex omega = complex(1.0, 0.0); //e ^ 0
for(int k = j; k < j + i / 2; ++ k)
{
complex x = a[k], y = omega * a[k + i / 2];
a[k] = x + y, a[k + i / 2] = x - y;
omega = omega * omega_n;
}
}
}
if(opt == -1)
for(int i = 0; i < len; ++ i)
a[i].real /= (double)len;
}
int ans[N << 1];
inline void convolute(complex *a, complex *b)
{
prepare(a, b);
fft(a, 1), fft(b, 1);
for(int i = 0; i < len; ++ i)
a[i] = a[i] * b[i];
fft(a, -1);
for(int i = 0; i < len; ++ i)
ans[i] = (int)(a[i].real + 0.5);
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("HDU1402.in", "r", stdin);
freopen("HDU1402.out", "w", stdout);
#endif
while(gets(str1) && gets(str2))
{
len1 = strlen(str1), len2 = strlen(str2);
memset(a, 0, sizeof(a));
memset(b, 0, sizeof(b));
for(int i = 0; i < len1; ++ i)
a[i] = complex(str1[len1 - i - 1] - '0', 0);
for(int i = 0; i < len2; ++ i)
b[i] = complex(str2[len2 - i - 1] - '0', 0);
convolute(a, b);
for(int i = 0; i < len; ++ i)
ans[i + 1] += ans[i] / 10, ans[i] %= 10;
for(; len && ! ans[len - 1]; -- len);
for(int i = len - 1; ~ i; -- i)
putchar(ans[i] + '0');
if(! len)
putchar('0');
putchar('\n');
}
}
NTT: 要求取模的数\(P\)是费马素数. 对于原根\(g\), 要确保有 \(g ^ 0 \ne g^1 \ne ... \ne g^{p - 2} (modP)\). NTT的过程相当于用 \(\omega_n = g^{ \frac{p - 1}{n}}\) 替代了 \(\omega_n = e^{\frac{2 \cdot \pi}{n} \cdot i}\)的FFT. \(\omega_i\)和\(inv(\omega_i)\)可以在预处理中求出.
const long long P = (479 << 21) + 1;
const long long G = 3;
inline long long quickPower(long long a, long long k, long long mod)
{
if(! k)
return 1;
long long ret = quickPower(a, k >> 1, mod);
ret = ret * ret % mod;
if(k & 1)
ret = ret * a % mod;
return ret;
}
const long long QUAN = 1 << 5;
long long omega_[QUAN];
inline void getOmega_n()
{
for(long long i = 0; i < QUAN; ++ i)
omega_[i] = quickPower(G, (P - 1) / (1 << i), P);
}
const long long LEN = 1 << 16;
char str1[LEN], str2[LEN];
#include<cstdio>
#include<cstring>
long long len1, len2;
long long a[LEN << 1], b[LEN << 1];
#include<algorithm>
long long len;
long long rev[LEN << 1];
inline void prepare()
{
long long mx = std::max(len1, len2) << 1;
len = 1;
long long bit = 0;
while(len < mx)
len <<= 1, ++ bit;
rev[0] = 0;
for(long long i = 0; i < len; ++ i)
rev[i] = rev[i >> 1] >> 1 | (i & 1) << (bit - 1);
}
inline void reverse(long long *a)
{
for(long long i = 0; i < len; ++ i)
if(rev[i] < i)
std::swap(a[i], a[rev[i]]);
}
inline void NTT(long long *a, long long opt)
{
reverse(a);
long long temp = 0;
for(long long i = 2; i <= len; i <<= 1)
{
++ temp;
int omega_i = ~ opt ? omega_[temp] : quickPower(omega_[temp], P - 2, P);
for(long long j = 0; j < len; j += i)
{
long long omega = 1;
for(long long k = j; k < j + i / 2; ++ k)
{
long long u = a[k], t = omega * a[k + i / 2] % P;
a[k] = (u + t) % P, a[k + i / 2] = (u - t + P) % P;
omega = omega * omega_i % P;
}
}
}
if(opt == -1)
{
long long inv = quickPower(len, P - 2, P);
for(long long i = 0; i < len; ++ i)
a[i] = a[i] * inv % P;
}
}
long long ans[LEN << 1];
inline void convolute(long long *a, long long *b)
{
prepare();
NTT(a, 1), NTT(b, 1);
for(long long i = 0; i < len; ++ i)
a[i] = a[i] * b[i] % P;
NTT(a, -1);
for(int i = 0; i < len; ++ i)
ans[i] = a[i];
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("HDU1402.in", "r", stdin);
#endif
getOmega_n();
while(gets(str1) && gets(str2))
{
len1 = strlen(str1), len2 = strlen(str2);
memset(a, 0, sizeof(a)), memset(b, 0, sizeof(b));
for(long long i = 0; i < len1; ++ i)
a[len1 - i - 1] = str1[i] - '0';
for(long long i = 0; i < len2; ++ i)
b[len2 - i - 1] = str2[i] - '0';
convolute(a, b);
for(int i = 0; i < len; ++ i)
ans[i + 1] += ans[i] / 10, ans[i] %= 10;
for(; len && ! ans[len - 1]; -- len);
for(int i = len - 1; ~ i; -- i)
putchar(ans[i] + '0');
if(! len)
putchar('0');
putchar('\n');
}
}
FFT/NTT模板 既 HDU1402 A * B Problem Plus的更多相关文章
- 多项式FFT/NTT模板(含乘法/逆元/log/exp/求导/积分/快速幂)
自己整理出来的模板 存在的问题: 1.多项式求逆常数过大(尤其是浮点数FFT) 2.log只支持f[0]=1的情况,exp只支持f[0]=0的情况 有待进一步修改和完善 FFT: #include&l ...
- FFT NTT 模板
NTT: #include<cstdio> #include<cstring> #include<algorithm> using namespace std; # ...
- 分治FFT/NTT 模板
题目要我们求$f[i]=\sum\limits_{j=1}^{i}f[i-j]g[j]\;mod\;998244353$ 直接上$NTT$肯定是不行的,我们不能利用尚未求得的项卷积 所以要用$CDQ$ ...
- [hdu1402]A * B Problem Plus(NTT)
解题关键:快速数论变换NTT模板. 注意$ans$数组的$ans[n]$一定要注意置$0$,或者结果从$n-1$开始遍历,这里很容易出错. 代码1:ACdreamer 的板子. 为什么要reverse ...
- FFT/NTT复习笔记&多项式&生成函数学习笔记Ⅰ
众所周知,tzc 在 2019 年(12 月 31 日)就第一次开始接触多项式相关算法,可到 2021 年(1 月 1 日)才开始写这篇 blog. 感觉自己开了个大坑( 多项式 多项式乘法 好吧这个 ...
- FFT \ NTT总结(多项式的构造方法)
前言.FFT NTT 算法 网上有很多,这里不再赘述. 模板见我的代码库: FFT:戳我 NTT:戳我 正经向:FFT题目解题思路 \(FFT\)这个玩意不可能直接裸考的..... 其实一般\(FF ...
- [学习笔记&教程] 信号, 集合, 多项式, 以及各种卷积性变换 (FFT,NTT,FWT,FMT)
目录 信号, 集合, 多项式, 以及卷积性变换 卷积 卷积性变换 傅里叶变换与信号 引入: 信号分析 变换的基础: 复数 傅里叶变换 离散傅里叶变换 FFT 与多项式 \(n\) 次单位复根 消去引理 ...
- FFT/NTT/MTT学习笔记
FFT/NTT/MTT Tags:数学 作业部落 评论地址 前言 这是网上的优秀博客 并不建议初学者看我的博客,因为我也不是很了解FFT的具体原理 一.概述 两个多项式相乘,不用\(N^2\),通过\ ...
- $FFT/NTT/FWT$题单&简要题解
打算写一个多项式总结. 虽然自己菜得太真实了. 好像四级标题太小了,下次写博客的时候再考虑一下. 模板 \(FFT\)模板 #include <iostream> #include < ...
随机推荐
- shell脚本,通过一个shell程序计算n的阶乘。
[root@localhost ~]# cat jiechen.sh #!/bin/bash #设计一个shell程序计算n的阶乘,要求: #.从命令行接收参数n; #.在程序开始后立即判断n的合法性 ...
- 全排列问题(DFS)
题目描述: 输出自然数1到n所有不重复的排列,即n的全排列,要求所产生的任一数字序列中不允许出现重复的数字. 输入格式: n(1≤n≤9) 输出格式: 由1-n组成的所有不重复的数字序列,每行一个序列 ...
- 【Java基础】java中的反射机制与动态代理
一.java中的反射机制 java反射的官方定义:在运行状态下,可以获取任意一个类的所有属性和方法,并且可通过某类任意一对象实例调用该类的所有方法.这种动态获取类的信息及动态调用类中方法的功能称为ja ...
- Git学习——版本切换
版本回退 回退到前面几个版本的命令如下: git reset --hard HEAD^ //回退到前一个版本 git reset --hard HEAD^^ //回退到前前一个版本 git reset ...
- Python9-day11-作业
# 1.编写装饰器,为多个函数加上认证的功能(用户的账号密码来源于文件),# 要求登录成功一次,后续的函数都无需再输入用户名和密码 FLAG = False def login(func): def ...
- 【实验吧】因缺思汀的绕过&&拐弯抹角&&Forms&&天网管理系统
<?php error_reporting(); if (!isset($_POST['uname']) || !isset($_POST['pwd'])) { echo '<form a ...
- Ubuntu 14.04在虚拟机上的桥接模式下设置静态IP
1.虚拟机--->虚拟机设置 将虚拟机设置为桥接模式 2.查看window 网卡以及IP信息 cmd下输入 ipconfig -all 可以看到,我的网卡为Realtek PCIe GBE Fa ...
- Java实现——Socket网络通信的机制以及实现举例
1. 网络间的进程通信与Socket TCP/IP协议族中网络层的IP地址可以唯一标识网络中的主机,而传输层的协议+端口可以唯一标识主机中的应用程序(进程).这样利用这三元组就可以标识网络的进程了,网 ...
- python基础学习笔记——生成器与推导式
生成器 首先我们来看看什么是个生成器,生成器本质就是迭代器 在python中有三种方式来获取生成器 1.通过生成器函数 2.通过各种推到式来实现生成器 3.通过数据的转换也可以获取生成器 首先,我们先 ...
- centos 部署 自定义(succes)
安装前先检查一下有没有安装好了的JDK,Tomcat,MySQL,不过一般都没有. 1.安装JDK 1.1 下载jdk,可以到官网查看不同版本的下载地址 wget --no-check-certifi ...