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:模运算基础知识 单位根介 ...
随机推荐
- 为你的网页图标(Favicon)添加炫丽的动画和图片
Favico.js 在让你的网页图标显示徽章,图像或视频.你设置可以轻松地在网页图标中使用动画,可以自定义类型的动画,背景颜色和文字颜色.它支持的动画,像幻灯片,渐变,弹出等等. 您可能感兴趣的相关文 ...
- jQuery原型方法each使用和源码分析
jQuery.each方法是jQuery的核心工具方法之一,通用例遍方法,可用于例遍对象和数组.不同于例遍 jQuery 对象的 $().each() 方法,此方法可用于例遍任何对象.通常需要两个参数 ...
- C#遍历得到checkboxlist选中值和设置选中项
得到选中项的value值并拼接成一个字符串返回 public string GetChecked(CheckBoxList checkList, string separator) { string ...
- SrsDataConnector The SQL Server Reporting Services account is a local user and is not supported.
这次使用OS+SQL的镜像还原系统后安装了CRM 2015,主要流程是 安装IIS/AD,SSRS ,CRM2015.自带的SQL中SSRS没有安装完全,需配置一下. 这一切都满顺利的,最后在安装 S ...
- Linux下运行windows程序
现在Winxp停止了支持,那我们的windows程序是否可以再linux上执行呢,如下是一些参考的信息 在您的 Linux/Mac 操作系统上运行 Windows 软件 http://www.wine ...
- Sharepoint学习笔记—习题系列--70-576习题解析 -(Q21-Q24)
Question 21 An application will be deployed in a SharePoint 2010 server farm that is managed by depa ...
- Java单例模式实现的几种方式
单例模式好多书上都是这么写的: public class SingleTon1 { private SingleTon1(){ } private static SingleTon1 instance ...
- Android 网络HTML查看器
本文实现一个基于Android的网络HTML查看器 新建项目,项目布局文件如下: <LinearLayout xmlns:android="http://schemas.android ...
- jax-rs中的一些参数标注简介(@PathParam,@QueryParam,@MatrixParam,@HeaderParam,@FormParam,@CookieParam)
先复习一下url的组成: scheme:[//[user:password@]host[:port]][/]path[?query][#fragment] jax-rs anotation @Path ...
- QBus 关注并推送实时公交信息
后台服务器定时根据关注列表,查询最近车辆,发送邮件进行推送