FFT,NTT 专题
学习傅里叶的基本性质及其代码,可以参考大神理解
还有 ACdream 的博客
贴一下NTT的模板:
using namespace std;
typedef long long ll; int n;
const ll MOD=;
const int N = ;
const int g=;
int len;
ll A[N];
long long a[N],b[N],wn[];
long long q_pow(long long x,long long y,long long P)
{
long long ans=;
while(y>)
{
if(y&)ans=ans*x%P;
x=x*x%P;
y>>=;
}
return ans;
}
void init()
{
for(int i=;i<;i++)
{
int t=<<i;
wn[i]=q_pow(g,(MOD-)/t,MOD);
}
}
///雷德算法,2^M=len,将第i位的数与“i的二进制反转之后的位”的数交换
void rader(long long F[],int len)
{
int j=len/;///模拟二进制反转进位的的位置
for(int i=;i<len-;i++)
{
if(i<j)swap(F[i],F[j]);///该出手时就出手
int k=len/;
while(j>=k)
{
j-=k;
k>>=;
}
if(j<k)j+=k;
}
}
void NTT(long long F[],int len,int t)
{
int id=;
rader(F,len);
for(int h=;h<=len;h<<=)
{
id++;
for(int j=;j<len;j+=h)
{
long long E=;
for(int k=j;k<j+h/;k++)
{
long long u=F[k];
long long v=(E*F[k+h/])%MOD;
F[k]=(u+v)%MOD;
F[k+h/]=((u-v)%MOD+MOD)%MOD;
E=(E*wn[id])%MOD;
}
}
}
if(t==-)
{
for(int i=;i<len/;i++)swap(F[i],F[len-i]);
long long ni=q_pow(len,MOD-,MOD);
for(int i=;i<len;i++)F[i]=(F[i]%MOD*ni)%MOD;
}
} void work()///卷积,点乘,插值
{
NTT(a,len,);
NTT(b,len,);
for(int i=;i<len;i++)
a[i]=(a[i]*b[i])%MOD;
NTT(a,len,-);
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("in.txt","r",stdin);
#endif
init();
int T_T;
scanf("%d",&T_T);
for(int kase=;kase<=T_T;kase++)
{
sc(n);
len=;
while(len<=*n)
len<<=;
/**
这部分就是你对公式的变形并把他转化为卷积形式,分别存在a[],b[]里
*/
work();
}
return 0;
}
对于傅里叶运用的要点,要认真对待对下面卷积公式的理解

训练:
传送门:hdu 5829 Rikka with Subset
题意:给你一个数组A[],然后计算F[k],F[k]指A[]所有子集中,先对每个子集前k大的数的和,然后再对把所以子集所求值求和
思路:因为我也是初学,所以我找的一个大神的博客学习的http://blog.csdn.net/cqu_hyx/article/details/52194696
对于其中的几点,我做一点补充:
- f[k]计算的是第k大的数对答案的贡献,而比他大的数的贡献没有计算;不过只需要累加分f[1]..f[k-1]就是前k大的数的和了
- 对比以上卷积公式,我们得到的是 a[i]=2n-i/i! , b[i]=A[i]*(i-1)! ;如果我们b[0]=A[1]*0!,那么我们reverse一下,b[i]=b[n-i]了;在我们推导的f[k]公式里,f[k]是与a[i]*b[i+k]相关的,且i最大为(n-k),经过我们对b数组reverse,f[k]是与a[i]*b[(n-k)-i]相关的,这刚好和上面的卷积公式一致,所以我们可以放心ntt了。
- 由卷积公式可知,y[n-k]是a[i]*b[(n-k)-i]的卷积结果,而这个结果存在a[]里;并且f[k]也等于a[i]*b[(n-k)-i]的卷积,所以f[k]与y[n-k]即a[n-k]相关
/**************************************************************
Problem:hdu 5829 Rikka with Subset
User: youmi
Language: C++
Result: Accepted
Time:2605MS
Memory:11804K
****************************************************************/
//#pragma comment(linker, "/STACK:1024000000,1024000000")
//#include<bits/stdc++.h>
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <map>
#include <stack>
#include <set>
#include <sstream>
#include <cmath>
#include <queue>
#include <deque>
#include <string>
#include <vector>
#define zeros(a) memset(a,0,sizeof(a))
#define ones(a) memset(a,-1,sizeof(a))
#define sc(a) scanf("%d",&a)
#define sc2(a,b) scanf("%d%d",&a,&b)
#define sc3(a,b,c) scanf("%d%d%d",&a,&b,&c)
#define scs(a) scanf("%s",a)
#define sclld(a) scanf("%I64d",&a)
#define pt(a) printf("%d\n",a)
#define ptlld(a) printf("%I64d\n",a)
#define rep(i,from,to) for(int i=from;i<=to;i++)
#define irep(i,to,from) for(int i=to;i>=from;i--)
#define Max(a,b) ((a)>(b)?(a):(b))
#define Min(a,b) ((a)<(b)?(a):(b))
#define lson (step<<1)
#define rson (lson+1)
#define eps 1e-6
#define oo 0x3fffffff
#define TEST cout<<"*************************"<<endl
const double pi=*atan(1.0); using namespace std;
typedef long long ll; int n;
const ll MOD=;
const int N = ;
const int g=;
int len;
ll inv2;
ll A[N];
ll inv[N],fac[N],f[N],bit[N];
long long a[N],b[N],wn[];
long long q_pow(long long x,long long y,long long P)
{
long long ans=;
while(y>)
{
if(y&)ans=ans*x%P;
x=x*x%P;
y>>=;
}
return ans;
}
void init()
{
for(int i=;i<;i++)
{
int t=<<i;
wn[i]=q_pow(g,(MOD-)/t,MOD);
}
inv[]=inv[]=;
rep(i,,1e5)
inv[i]=(inv[i-]*q_pow(i,MOD-,MOD))%MOD;
fac[]=fac[]=;
rep(i,,1e5)
fac[i]=(fac[i-]*i)%MOD;
bit[]=;
rep(i,,1e5)
bit[i]=bit[i-]*%MOD;
inv2=q_pow(,MOD-,MOD);
}
///雷德算法,2^M=len,将第i位的数与“i的二进制反转之后的位”的数交换
void rader(long long F[],int len)
{
int j=len/;///模拟二进制反转进位的的位置
for(int i=;i<len-;i++)
{
if(i<j)swap(F[i],F[j]);///该出手时就出手
int k=len/;
while(j>=k)
{
j-=k;
k>>=;
}
if(j<k)j+=k;
}
}
void NTT(long long F[],int len,int t)
{
int id=;
rader(F,len);
for(int h=;h<=len;h<<=)
{
id++;
for(int j=;j<len;j+=h)
{
long long E=;
for(int k=j;k<j+h/;k++)
{
long long u=F[k];
long long v=(E*F[k+h/])%MOD;
F[k]=(u+v)%MOD;
F[k+h/]=((u-v)%MOD+MOD)%MOD;
E=(E*wn[id])%MOD;
}
}
}
if(t==-)
{
for(int i=;i<len/;i++)swap(F[i],F[len-i]);
long long ni=q_pow(len,MOD-,MOD);
for(int i=;i<len;i++)F[i]=(F[i]%MOD*ni)%MOD;
}
} void work()///卷积,点乘,插值
{
NTT(a,len,);
NTT(b,len,);
for(int i=;i<len;i++)
a[i]=(a[i]*b[i])%MOD;
NTT(a,len,-);
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("in.txt","r",stdin);
#endif
init();
int T_T;
scanf("%d",&T_T);
for(int kase=;kase<=T_T;kase++)
{
sc(n);
len=;
while(len<=*n)
len<<=;
rep(i,,n)
sclld(A[i]);
sort(A+,A++n,greater<ll>());
zeros(a);zeros(b);
rep(i,,n-)
a[i]=(bit[n-i]*inv[i])%MOD;
rep(i,,n-)
b[i]=(A[i+]*fac[i])%MOD;
reverse(b,b+n);
work();
ll r=inv2;
f[]=;
rep(i,,n)
{
f[i]=a[n-i]*inv[i-]%MOD*r%MOD;
r=r*inv2%MOD;
f[i]=(f[i]+f[i-])%MOD;
printf("%I64d ",f[i]);
}
puts("");
}
}
FFT,NTT 专题的更多相关文章
- FFT与NTT专题
先不管旋转操作,考虑化简这个差异值 $$begin{aligned}sum_{i=1}^n(x_i-y_i-c)^2&=sum_{i=1}^n(x_i-y_i)^2+nc^2-2csum_{i ...
- 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总结
FFT&NTT总结 一些概念 \(DFT:\)离散傅里叶变换\(\rightarrow O(n^2)\)计算多项式卷积 \(FFT:\)快速傅里叶变换\(\rightarrow O(nlogn ...
- 快速构造FFT/NTT
@(学习笔记)[FFT, NTT] 问题概述 给出两个次数为\(n\)的多项式\(A\)和\(B\), 要求在\(O(n \log n)\)内求出它们的卷积, 即对于结果\(C\)的每一项, 都有\[ ...
- FFT/NTT模板 既 HDU1402 A * B Problem Plus
@(学习笔记)[FFT, NTT] Problem Description Calculate A * B. Input Each line will contain two integers A a ...
- FFT/NTT基础题总结
在学各种数各种反演之前把以前做的$FFT$/$NTT$的题整理一遍 还请数论$dalao$口下留情 T1快速傅立叶之二 题目中要求求出 $c_k=\sum\limits_{i=k}^{n-1}a_i* ...
- $FFT/NTT/FWT$题单&简要题解
打算写一个多项式总结. 虽然自己菜得太真实了. 好像四级标题太小了,下次写博客的时候再考虑一下. 模板 \(FFT\)模板 #include <iostream> #include < ...
- FFT&NTT数学解释
FFT和NTT真是噩梦呢 既然被FFT和NTT坑够了,坑一下其他的人也未尝不可呢 前置知识 多项式基础知识 矩阵基础知识(之后会一直用矩阵表达) FFT:复数基础知识 NTT:模运算基础知识 单位根介 ...
随机推荐
- 20款风格独特的搜索框 PSD 设计素材免费下载
搜索框是网站中的最常用的组件一直,但有时候,搜索框因为设计不够新颖容易被访客忽视.通过提高一个搜索框的外观设计,最终对整体的网页设计带来好的变化.这份列表将是一个很好的资源,尤其是对设计师.希望你会喜 ...
- 【JavaScript】内置对象Math
Math是具有用于数学常数和函数的属性和方法一内置对象.不是函数对象. 描述编辑 不像其他的全局对象,Math不是一个构造函数.所有属性和方法Math都是静态的.你指的是常数pi为Math.PI你调用 ...
- Windows安装apache2.4
The primary Windows platform for running Apache 2.4 is Windows 2000 or later. Always obtain and inst ...
- 汉王云名片识别(SM)组件开发详解
大家好,最近在DeviceOne平台上做了一个汉王云名片识别的功能组件.下面把我开发过程给大家做一个分享,希望可以帮助到大家. 下面我把我的思路给大家讲解一下. 1.找到我要集成的sdk,也就是汉 ...
- 每天checklist所用到的T-CODE
1.1重点检查 作业 事务码 检查过程 检查R/3系统是否已经启动 · 登录到R/3系统 检查每日备份是否正常 DB12-Backup Logs:Overview · 检查数据库备份 · 检查数据库备 ...
- sharepoint2010问卷调查(4)-实现问卷的重复答复次数(采用自定义字段类型和JS)
sharepoint的问卷调查可以设置重复和一次答复.但是设置一次后,调查过的用户再进行答复.会提示如下图: 分析下:该提示用户体验很不好.给用户感觉是系统出问题了.因此网上有人提出用eventhan ...
- SharePoint 使用脚本为表单绑定事件
在SharePoint的使用过程中,我们经常需要为表单页面做一些特殊处理,比如说新建页面的时候有多选项的字段,但是只能选择指定数量的选项,尤其在新闻列表或者调查列表等特殊场景中,广泛使用. 下面,我们 ...
- 连接QuickBooks Online实现于IOS App数据同步功能的个人记录
公司项目需要用WebService与QBO实现后台数据同步,由于国内没有做过类似第三方产品接口的资料,前前后后找了N久,终于实现功能,现把实现功能步骤贴上来分享: QBO开发者地址(主要用于创建QBO ...
- JavaScript MVC框架和语言总结[infoq]
infoq关于javascript的语言和框架的总结,非常全面,值得一读. http://www.infoq.com/minibooks/emag-javascript Contents of the ...
- Android--ListView下拉刷新
整理了下以前写的小项目,ListView的下拉刷新,虽然小但还是想纪念下..适合新手看,大神略过... 效果图: 代码: 实体类 package com.example.listviewre ...