模板 - 数学 - 多项式 - 快速数论变换/NTT
Huffman分治的NTT,常数一般。使用的时候把多项式的系数们放进vector里面,然后调用solve就可以得到它们的乘积。注意这里默认最大长度是1e6,可能需要改变。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
int a[200005], b[200005], btop;
const int MAXN = 1e6, MAXLOGN = 20, mod = 998244353;
int add_mod(int x, int y) {
x += y;
if(x >= mod)
x -= mod;
return x;
}
int sub_mod(int x, int y) {
x -= y;
if(x < 0)
x += mod;
return x;
}
ll mul_mod(ll x, int y) {
x *= y;
if(x >= mod)
x %= mod;
return x;
}
int pow_mod(ll x, int n) {
ll res = 1;
while(n) {
if(n & 1)
res = mul_mod(res, x);
x = mul_mod(x, x);
n >>= 1;
}
return res;
}
int gl[MAXLOGN + 1];
void init() {
for(int len = 2; len <= MAXN; len <<= 1)
gl[__builtin_ctz(len)] = pow_mod(3, (mod - 1) / len);
}
void NTT(int a[], int n, int op) {
for(int i = 1, j = n >> 1; i < n - 1; ++i) {
if(i < j)
swap(a[i], a[j]);
int k = n >> 1;
while(k <= j) {
j -= k;
k >>= 1;
}
j += k;
}
for(int len = 2; len <= n; len <<= 1) {
int g = gl[__builtin_ctz(len)];
for(int i = 0; i < n; i += len) {
int w = 1;
for(int j = i; j < i + (len >> 1); ++j) {
int u = a[j], t = mul_mod(a[j + (len >> 1)], w);
a[j] = add_mod(u, t), a[j + (len >> 1)] = sub_mod(u, t);
w = mul_mod(w, g);
}
}
}
if(op == -1) {
reverse(a + 1, a + n);
int inv = pow_mod(n, mod - 2);
for(int i = 0; i < n; ++i)
a[i] = mul_mod(a[i], inv);
}
}
int A[MAXN + 5], B[MAXN + 5];
int pow2(int x) {
int res = 1;
while(res < x)
res <<= 1;
return res;
}
void convolution(int A[], int B[], int Asize, int Bsize) {
int n = pow2(Asize + Bsize - 1);
memset(A + Asize, 0, sizeof(A[0]) * (n - Asize));
memset(B + Bsize, 0, sizeof(B[0]) * (n - Bsize));
NTT(A, n, 1);
NTT(B, n, 1);
for(int i = 0; i < n; ++i)
A[i] = mul_mod(A[i], B[i]);
NTT(A, n, -1);
return;
}
vector<int> vec[200005], evec;
struct PriorityQueueNode {
int siz, id;
bool operator<(const PriorityQueueNode &pqn) const {
return siz > pqn.siz;
}
} pqn;
priority_queue<PriorityQueueNode> pq;
void solve() {
//哈夫曼分治
init();
while(pq.size() > 1) {
int Aid = pq.top().id, Asize = vec[Aid].size();
for(int i = 0; i < Asize; ++i)
A[i] = vec[Aid][i];
pq.pop();
int Bid = pq.top().id, Bsize = vec[Bid].size();
for(int i = 0; i < Bsize; ++i)
B[i] = vec[Bid][i];
pq.pop();
convolution(A, B, Asize, Bsize);
Asize = Asize + Bsize - 1;
vec[Aid].resize(Asize);
for(int i = 0; i < Asize; ++i)
vec[Aid][i] = A[i];
pq.push({Asize, Aid});
vec[Bid] = evec;
}
}
int main() {
#ifdef KisekiPurin
freopen("KisekiPurin.in", "r", stdin);
#endif // KisekiPurin
int n;
scanf("%d", &n);
for(int i = 1; i <= n; ++i)
scanf("%d", &a[i]);
sort(a + 1, a + 1 + n);
btop = 0;
for(int i = 1; i <= n; ++i) {
if(a[i] != a[i - 1])
b[++btop] = 1;
else
++b[btop];
}
sort(b + 1, b + 1 + btop);
for(int i = 1; i <= btop; ++i) {
while(vec[0].size() < b[i] + 1)
vec[0].push_back(1);
vec[i] = vec[0];
pq.push({vec[i].size(), i});
}
solve();
printf("%d\n", vec[pq.top().id][pq.top().siz >> 1]);
return 0;
}
模板 - 数学 - 多项式 - 快速数论变换/NTT的更多相关文章
- Algorithm: 多项式乘法 Polynomial Multiplication: 快速傅里叶变换 FFT / 快速数论变换 NTT
Intro: 本篇博客将会从朴素乘法讲起,经过分治乘法,到达FFT和NTT 旨在能够让读者(也让自己)充分理解其思想 模板题入口:洛谷 P3803 [模板]多项式乘法(FFT) 朴素乘法 约定:两个多 ...
- 【算法】快速数论变换(NTT)初探
[简介] 快速傅里叶变换(FFT)运用了单位复根的性质减少了运算,但是每个复数系数的实部和虚部是一个余弦和正弦函数,因此系数都是浮点数,而浮点数的运算速度较慢且可能产生误差等精度问题,因此提出了以数论 ...
- JZYZOJ 2041 快速数论变换 NTT 多项式
http://172.20.6.3/Problem_Show.asp?id=2041 https://blog.csdn.net/ggn_2015/article/details/68922404 代 ...
- 快速数论变换NTT模板
51nod 1348 乘积之和 #include <cmath> #include <iostream> #include <cstdio> #include &l ...
- [快速数论变换 NTT]
先粘一个模板.这是求高精度乘法的 #include <bits/stdc++.h> #define maxn 1010 using namespace std; char s[maxn]; ...
- 数学(快速数论变换):SDOI2015 序列统计
[题目描述] 小C有一个集合S,里面的元素都是小于M的非负整数.他用程序编写了一个数列生成器,可以生成一个长度为N的数列,数列中的每个数都属于集合S. 小C用这个生成器生成了许多这样的数列.但是小C有 ...
- 快速数论变换(NTT)小结
NTT 在FFT中,我们需要用到复数,复数虽然很神奇,但是它也有自己的局限性--需要用double类型计算,精度太低 那有没有什么东西能够代替复数且解决精度问题呢? 这个东西,叫原根 原根 阶 若\( ...
- 从傅里叶变换(FFT)到数论变换(NTT)
FFT可以用来计算多项式乘法,但是复数的运算中含有大量的浮点数,精度较低.对于只有整数参与运算的多项式,有时,\(\text{NTT(Number-Theoretic Transform)}\)会是更 ...
- 多项式 之 快速傅里叶变换(FFT)/数论变换(NTT)/常用套路【入门】
原文链接https://www.cnblogs.com/zhouzhendong/p/Fast-Fourier-Transform.html 多项式 之 快速傅里叶变换(FFT)/数论变换(NTT)/ ...
随机推荐
- 转 Html转pdf的工具——wkhtmltopdf
下载地址:http://wkhtmltopdf.org/downloads.html 安装好以后需要在系统环境变量变量名为”Path”的后添加:;D:\wkhtmltopdf\bin 也就是你安装的目 ...
- python BeautifulSoup4--例子
from bs4 import BeautifulSoup import requests import re #请求博客园首页 r=requests.get('http://www.cnblogs. ...
- 【openshift】在Openshift上通过yaml部署应用
在Openshift上通过yaml部署应用 1.通过直接执行yaml 通过如下命令直接执行 oc create -f nginx.yml nginx.yml apiVersion: v1 items: ...
- Fortify漏洞之 Privacy Violation(隐私泄露)和 Null Dereference(空指针异常)
继续对Fortify的漏洞进行总结,本篇主要针对 Privacy Violation(隐私泄露) 和 Null Dereference(空指针异常) 的漏洞进行总结,如下: 1.1.产生原因: Pri ...
- SAP官网发布的react教程
大家学习React的时候,用的是什么教程呢?Jerry当时用的阮一峰博客上的入门教程,因为React使用的JSX语法并不是所有的浏览器都支持,所以还得使用browser.js在浏览器端将JSX转换成J ...
- SAP云平台里的三叉戟应用
大家第一次看到SAP MTA这个词组,会联想到什么? Jerry第一次看到的时候,联想到的是那一个个足坛著名的三叉戟攻击组合. 海皇波塞冬(Poseidon),奥林匹斯十二神中地位仅次于宙斯的大神,海 ...
- MySQL Backup--Xtrabackup备份设置锁等待问题
问题描述 innobackupex备份过程需要保证备份数据一致性,通过刷新表缓存和加全局读锁(FLUSH TABLES WITH READ LOCK)获取备份位点,而为防止锁等待超时,会先设置: SE ...
- Windows下学习C语言有哪些集成开发软件?
前言 初学者学习C语言遇到的最大困难想必就是搭建环境了,相当多的初学者就是被搭建环境导致放弃了学习编程,就我自己的经验而言,初学编程不应该受限于环境,使用成熟好用的环境就可以了,之后熟悉一些可以在慢慢 ...
- Linux中快速对字符串进行加密
1)进行base64的加密和解密 [root@VM_0_10_centos opt]# echo hello |base64aGVsbG8K[root@VM_0_10_centos opt]# ech ...
- 华为云PaaS首席科学家:Cloud Native +AI,企业数字化转型的最佳拍档
近日,在2019华为全球分析师大会期间,华为云PaaS首席科学家熊英博士在+智能,见未来(华为云&大数据)的分论坛上,从云计算行业发展谈起,深入云原生发展趋势,对华为云智能应用平台做了深度解读 ...