先粘一个模板。这是求高精度乘法的

#include <bits/stdc++.h>
#define maxn 1010
using namespace std; char s[maxn]; typedef long long ll;
ll A[maxn], B[maxn]; const int md = 998244353, G = 3; int n; ll power_mod(ll a, ll b){
ll ret = 1;
while(b > 0){
if(b & 1)ret = ret * a % md;
b >>= 1;
a = a * a % md;
}return ret;
} void NTT(ll A[], int n, int type){
for(int i = 0, j = 0; i < n; i ++){
if(i < j)swap(A[i], A[j]);
for(int t = n >> 1; (j ^= t) < t; t >>= 1);
} for(int k = 2; k <= n; k <<= 1){
ll wn = type > 0 ? power_mod(G, (md - 1) / k) : power_mod(G, (md - 1) - (md - 1) / k);
for(int i = 0; i < n; i += k){
ll w = 1;
for(int j = 0; j < k >> 1; j ++){
ll T = w * A[i+j+(k>>1)] % md;
A[i+j+(k>>1)] = (A[i+j] - T) % md;
A[i+j] = (A[i+j] + T) % md;
w = w * wn % md;
}
}
} if(type < 0){
ll inv = power_mod(n, md - 2);
for(int i = 0; i < n; i ++)
A[i] = A[i] * inv % md;
}
} int main(){
freopen("mul.in", "r", stdin);
freopen("mul.out", "w", stdout);
scanf("%s", s);
int n1 = strlen(s);
for(int i = n1 - 1; ~i; i --)
A[n1-i-1] = s[i] ^ 48;
scanf("%s", s);
int n2 = strlen(s);
for(int i = n2 - 1; ~i; i --)
B[n2-i-1] = s[i] ^ 48;
for(n = 1; n <= n1 + n2; n <<= 1);
NTT(A, n, 1), NTT(B, n, 1);
for(int i = 0; i < n; i ++)
A[i] = A[i] * B[i] % md;
NTT(A, n, -1);
for(int i = 0; i < n; i ++){
A[i] = (A[i] + md) % md;
A[i+1] += A[i] / 10, A[i] %= 10;
}
while(n && A[n] == 0) n --;
for(int i = n; i >= 0; i --)
printf("%lld", A[i]);
return 0;
}

[SDOI 2015]序列统计

取指标变成加法问题,构造生成函数F(x),F(x)的n次方就是答案。

注意指标要mod M-1

还有注意0的问题,如果x!=0就不用管数据中的0,否则需要两种情况求和(然而数据中x并不等于0我就没写)

#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdio>
#include <cmath>
#define maxn 50010
using namespace std;
typedef long long ll;
const int md = 1004535809, G = 3; int N, M, X, S, a[maxn], Log[maxn], n;
ll F[maxn], H[maxn], ret[maxn]; int p[maxn], primes, vis[maxn]; ll power_mod(ll a, ll b, ll md){
ll ret = 1;
while(b > 0){
if(b & 1) ret = ret * a % md;
b >>= 1;
a = a * a % md;
}return ret;
} void pre_prime(){
int n = 20000;
for(int i = 2; i <= n; i ++){
if(!vis[i])p[++ primes] = i;
for(int j = 1; j <= primes; j ++){
if(i * p[j] > n)break;
vis[i * p[j]] = true;
if(i % p[j] == 0)break;
}
}
} int getG(int M){
pre_prime();
int ret = 2;
for(; ; ret ++){
bool flag = true;
for(int i = 1; i <= primes; i ++){
if(M-1 < p[i])break;
if((M-1) % p[i] == 0){
if(power_mod(ret, (M - 1) / p[i], M) == 1){
flag = false;
break;
}
}
}
if(flag)return ret;
}
} void NTT(ll A[], int n, int type){
for(int i = 0, j = 0; i < n; i ++){
if(i > j)swap(A[i], A[j]);
for(int t = n >> 1; (j ^= t) < t; t >>= 1);
} for(int k = 2; k <= n; k <<= 1){
ll wn = type > 0 ? power_mod(G, (md-1)/k, md) : power_mod(G, md-1-(md-1)/k, md);
for(int i = 0; i < n; i += k){
ll w = 1;
for(int j = 0; j < k >> 1; j ++){
ll T = w * A[i+j+(k>>1)];
A[i+j+(k>>1)] = (A[i+j] - T + md) % md;
A[i+j] = (A[i+j] + T) % md;
w = w * wn % md;
}
}
} if(type < 0){
ll inv = power_mod(n, md - 2, md);
for(int i = 0; i < n; i ++)
A[i] = A[i] * inv % md;
}
} void CF(ll A[]){
for(int i = 0; i < n; i ++)H[i] = F[i];
NTT(A, n, 1), NTT(H, n, 1);
for(int i = 0; i < n; i ++)
A[i] = A[i] * H[i] % md;
NTT(A, n, -1);
for(int i = (M - 1); i < n; i ++)
(A[i % (M - 1)] += A[i]) %= md, A[i] = 0;
} void power(int b){
ret[0] = 1;
while(b){
if(b & 1)CF(ret);
b >>= 1;
CF(F);
}
} int main(){
scanf("%d%d%d%d", &N, &M, &X, &S);
for(int i = 1; i <= S; i ++)
scanf("%d", &a[i]); for(n = 1; n <= M; n <<= 1); n <<= 1; ll nw = 1, Gn = getG(M);
for(int i = 0; i < M-1; i ++)
Log[nw] = i, nw = nw * Gn % M; for(int i = 1; i <= S; i ++)
if(a[i])F[Log[a[i]]] = 1; power(N);
printf("%lld\n", (ret[Log[X]] + md) % md);
return 0;
}

[COGS 2287]疯狂的机器人

这里有Catalan数的链接

#include <bits/stdc++.h>
#define maxn 300010
using namespace std;
typedef long long ll;
int n;
const int md = 998244353, G = 3; ll power_mod(ll a, ll b = md - 2){
ll ret = 1;
while(b > 0){
if(b & 1)ret = ret * a % md;
b >>= 1;
a = a * a % md;
}return ret;
} ll fac[maxn], inv[maxn], f[maxn]; void NTT(ll* A, int n, int type){
for(int i = 0, j = 0; i < n; i ++){
if(i > j)swap(A[i], A[j]);
for(int t = n >> 1; (j ^= t) < t; t >>= 1);
} for(int k = 2; k <= n; k <<= 1){
ll wn = power_mod(G, type > 0 ? (md-1) / k : md-1 - (md-1) / k);
for(int i = 0; i < n; i += k){
ll w = 1;
for(int j = 0; j < k >> 1; j ++){
ll T = w * A[i+j+(k>>1)] % md;
A[i+j+(k>>1)] = (A[i+j] - T) % md;
A[i+j] = (A[i+j] + T) % md;
w = w * wn % md;
}
}
} if(type == -1){
ll inv = power_mod(n);
for(int i = 0; i < n; i ++)
A[i] = A[i] * inv % md;
}
} int main(){
freopen("crazy_robot.in", "r", stdin);
freopen("crazy_robot.out", "w", stdout);
scanf("%d", &n);
fac[0] = inv[0] = 1;
for(int i = 1; i <= 2 * n; i ++)
fac[i] = fac[i-1] * i % md;
inv[2 * n] = power_mod(fac[2 * n]);
for(int i = 2 * n - 1; i >= 1; i --)
inv[i] = inv[i+1] * (i+1) % md;
for(int i = 0; i <= n; i ++){
if(i & 1){f[i] = 0;continue;}
f[i] = fac[i] * inv[i / 2] % md * inv[i / 2 + 1] % md * inv[i] % md;
} int _N = 1;
for(; _N <= n + n; _N <<= 1);
NTT(f, _N, 1);
for(int i = 0; i < _N; i ++)
f[i] = f[i] * f[i] % md;
NTT(f, _N, -1);
ll ans = 0;
for(int i = 0; i <= n; i ++)
(ans += inv[n - i] * f[i]) %= md;
cout << (ans * fac[n] % md + md) % md << endl;
return 0;
}

[NOI十连测3007]卡常大法好。

#include <cstring>
#include <cstdio>
#define maxn 150010 const int md = 998244353, G = 3; int R;
#define fastcall __attribute__((optimize("-Os")))
#define IL __inline__ __attribute__((always_inline))
fastcall IL int mul_mod(int a, int b){
__asm__ __volatile__ ("\tmull %%ebx\n\tdivl %%ecx\n" :"=d"(R):"a"(a),"b"(b),"c"(md));
return R;
} int n, N; int f[maxn], g[maxn], h[maxn], fac[maxn], inv[maxn], pw[maxn], tmp[maxn]; fastcall IL int power_mod(int a, long long b = md - 2){
int ret = 1;
while(b > 0){
if(b & 1)ret = mul_mod(ret, a);
b >>= 1;
a = mul_mod(a, a);
}return ret;
} fastcall IL void swap(int& a, int& b){
a ^= b ^= a ^= b;
} fastcall IL void NTT(int* A, int n, int type){
for(int i = 0, j = 0; i < n; i ++){
if(i > j)swap(A[i], A[j]);
for(int t = n >> 1; (j ^= t) < t; t >>= 1);
} for(int k = 2; k <= n; k <<= 1){
int wn = power_mod(G, type > 0 ? (md-1)/k : (md-1)-(md-1)/k);
for(int i = 0, m = k >> 1; i < n; i += k){
int w = 1;
for(int j = 0; j < k >> 1; j ++){
int T = mul_mod(w, A[i+j+m]);
A[i+j+m] = (A[i+j] - T + md) % md;
A[i+j] = (A[i+j] + T) % md;
w = mul_mod(w, wn);
}
}
} if(type < 0){
int inv = power_mod(n);
for(int i = 0; i < n; i ++)
A[i] = mul_mod(A[i], inv);
}
} fastcall void Getinv(int* a, int* b, int n){
if(n == 1){b[0] = power_mod(a[0]); return;}
Getinv(a, b, n >> 1);
memcpy(tmp, a, sizeof(a[0]) * n);
NTT(tmp, n << 1, 1);
NTT(b, n << 1, 1);
for(int i = 0; i < n << 1; i ++)
b[i] = mul_mod(b[i], (2ll - mul_mod(b[i], tmp[i]) + md) % md);
NTT(b, n << 1, -1);
memset(b + n, 0, sizeof(a[0]) * n);
} int F[30010][16];
int K; fastcall void cdq(int l, int r){
if(l == r)return;
int mid = l + r >> 1, len = r - l + 1;
cdq(l, mid);
for(n = 1; n <= len; n <<= 1);
for(int i = 0; i < n; i ++)f[i] = h[i] = 0;
for(int i = l; i <= mid; i ++)
f[i-l] = mul_mod(F[i][K-1] + F[i][K], inv[i]);
h[0] = 0;
for(int i = 1; i < n; i ++)
h[i] = mul_mod(g[i], inv[i-1]);
if(n<=32) {
for(int i = 0; i < n; i ++)tmp[i] = 0;
for(int i = 0 ; i < n ; ++ i) {
for(int j = 0 ; j <= i ; ++ j) {
tmp[i] += mul_mod(h[j], f[i-j]);
if(tmp[i]>=md) tmp[i] -= md;
}
}
for(int i = 0 ; i < n ; ++ i) h[i] = tmp[i];
} else {
NTT(f, n, 1), NTT(h, n, 1);
for(int i = 0; i < n; i ++)
h[i] = mul_mod(h[i], f[i]);
NTT(h, n, -1);
}
for(int i = mid + 1; i <= r; i ++){
F[i][K] += mul_mod(h[i-l], fac[i-1]);
if(F[i][K] >= md)F[i][K] -= md;
}
cdq(mid + 1, r);
} int main(){
N = 30000;
for(n = 1; n <= N; n <<= 1);
fac[0] = inv[0] = 1;
for(int i = 1; i <= n; i ++)fac[i] = mul_mod(fac[i - 1], i);
inv[n] = power_mod(fac[n]);
for(int i = n - 1; i >= 1; i --)inv[i] = mul_mod(inv[i + 1], i + 1);
for(long long i = 0; i <= n; i ++)pw[i] = power_mod(2, i * (i - 1) / 2);
for(int i = 1; i < n; i ++)h[i] = mul_mod(pw[i], inv[i - 1]);
for(int i = 0; i < n; i ++)f[i] = mul_mod(pw[i], inv[i]);
Getinv(f, g, n);
n <<= 1;
NTT(g, n, 1);
NTT(h, n, 1);
for(int i = 0; i < n; i ++)
g[i] = mul_mod(g[i], h[i]);
NTT(g, n, -1);
for(int i = 1; i <= N; i ++)
g[i] = mul_mod(g[i], fac[i - 1]); for(int i = 0; i <= N; i ++)F[i][0] = pw[i];
for(int i = 1; i <= 15; i ++)K = i, cdq(0, N); static int S[20][20];
S[0][0] = 1;
for(int i = 1; i <= 15; i ++)
for(int j = 1; j <= i; j ++){
S[i][j] = mul_mod(S[i-1][j], j) + S[i-1][j-1];
if(S[i][j] >= md)S[i][j] -= md;
} int test, n, m;
scanf("%d", &test);
while(test --){
scanf("%d%d", &n, &m);
int ans = 0;
for(int i = 0; i <= m; i ++){
ans += mul_mod(mul_mod(S[m][i], F[n][i]), fac[i]);
if(ans >= md)ans -= md;
}
printf("%d\n", ans);
}
return 0;
}

  

  

[快速数论变换 NTT]的更多相关文章

  1. 【算法】快速数论变换(NTT)初探

    [简介] 快速傅里叶变换(FFT)运用了单位复根的性质减少了运算,但是每个复数系数的实部和虚部是一个余弦和正弦函数,因此系数都是浮点数,而浮点数的运算速度较慢且可能产生误差等精度问题,因此提出了以数论 ...

  2. Algorithm: 多项式乘法 Polynomial Multiplication: 快速傅里叶变换 FFT / 快速数论变换 NTT

    Intro: 本篇博客将会从朴素乘法讲起,经过分治乘法,到达FFT和NTT 旨在能够让读者(也让自己)充分理解其思想 模板题入口:洛谷 P3803 [模板]多项式乘法(FFT) 朴素乘法 约定:两个多 ...

  3. JZYZOJ 2041 快速数论变换 NTT 多项式

    http://172.20.6.3/Problem_Show.asp?id=2041 https://blog.csdn.net/ggn_2015/article/details/68922404 代 ...

  4. 快速数论变换(NTT)小结

    NTT 在FFT中,我们需要用到复数,复数虽然很神奇,但是它也有自己的局限性--需要用double类型计算,精度太低 那有没有什么东西能够代替复数且解决精度问题呢? 这个东西,叫原根 原根 阶 若\( ...

  5. 模板 - 数学 - 多项式 - 快速数论变换/NTT

    Huffman分治的NTT,常数一般.使用的时候把多项式的系数们放进vector里面,然后调用solve就可以得到它们的乘积.注意这里默认最大长度是1e6,可能需要改变. #include<bi ...

  6. 快速数论变换NTT模板

    51nod 1348 乘积之和 #include <cmath> #include <iostream> #include <cstdio> #include &l ...

  7. 从傅里叶变换(FFT)到数论变换(NTT)

    FFT可以用来计算多项式乘法,但是复数的运算中含有大量的浮点数,精度较低.对于只有整数参与运算的多项式,有时,\(\text{NTT(Number-Theoretic Transform)}\)会是更 ...

  8. 多项式 之 快速傅里叶变换(FFT)/数论变换(NTT)/常用套路【入门】

    原文链接https://www.cnblogs.com/zhouzhendong/p/Fast-Fourier-Transform.html 多项式 之 快速傅里叶变换(FFT)/数论变换(NTT)/ ...

  9. 「算法笔记」快速数论变换(NTT)

    一.简介 前置知识:多项式乘法与 FFT. FFT 涉及大量 double 类型数据操作和 \(\sin,\cos\) 运算,会产生误差.快速数论变换(Number Theoretic Transfo ...

随机推荐

  1. simple_html_dom使用小结

    simple_html_dom使用小结 分类: PHP2012-08-31 14:24 3094人阅读 评论(0) 收藏 举报 htmlcallbackstringdivfunctionfile  1 ...

  2. ubuntu14.04安装dropbox

    官网地址: https://www.dropbox.com/install?os=lnx 自己的系统如果没有设置全局翻(qiang)代理,使用deb文件安装后不能直接使用,因为还需要到官网安装prop ...

  3. Hydra---Linux下的暴力美学

    引自:http://www.cnblogs.com/mchina/archive/2013/01/01/2840815.html 安装:http://www.91ri.org/2867.html yu ...

  4. debian下mysql主从配置

    1.确保master/slave只有一份/etc/mysql/my.cnf , 不要在其他地方再有my.cnf (如/etc/my.cnf  /usr/local之类) 2.master配置: 在[m ...

  5. 利用FFmpeg生成视频缩略图 2.1.6

    利用FFmpeg生成视频缩略图 1.下载FFmpeg文件包,解压包里的\bin\下的文件解压到 D:\ffmpeg\ 目录下. 下载地址 http://ffmpeg.zeranoe.com/build ...

  6. Java for LeetCode 077 Combinations

    Given two integers n and k, return all possible combinations of k numbers out of 1 ... n. For exampl ...

  7. codeforces 483C.Diverse Permutation 解题报告

    题目链接:http://codeforces.com/problemset/problem/483/C 题目意思:给出 n 和 k,要求输出一个含有 n 个数的排列 p1, p2, ...,pn,使得 ...

  8. 如何在Win8系统上建立WIFI热点

    1.首先将鼠标移到桌面左下角,单击右键,在弹出的快捷菜单中找到“命令提示符(管理员)”,点击 2.点击后,系统就以管理员权限打开了命令提示符,在命令提示符中输入以下命令“netsh wlan set ...

  9. Update startup files更新安装文件

    The service request did not complete because access to the service configuration manager was not gra ...

  10. JPush Wiki

    极光推送包含有通知与自定义消息两种类型的推送.本文描述他们的区别,以及建议的应用场景. 功能角度 通知 或者说 Push Notification,即指在手机的通知栏(状态栏)上会显示的一条通知信息. ...