一个套路:把式子推成卷积形式,然后用fft或ntt优化求解过程。

fft的扩展性不强,不可以在fft函数里多加骚操作--DeepinC

T1:多项式乘法

板子题

T2:快速傅立叶之二

另一个板子,小技巧:把一个数组反转过来,以符合卷积形式

T3:力

拆式子,把qj除到左边,然后把大于j的贡献和小于j的贡献分开考虑,对于小于j的,直接用fft统计,对于大于的,先反转再fft

T4:Normal

大神题,考虑把贡献拆成点对,对于两个点i与j,若i能对j作出贡献,则i到j的路径上没有断点,同样删除i到j路径以外的点不影响i与j之间的贡献,则i对j作出贡献的概率为

$\frac{1}{dis(i,j)}$则答案即为$\sum\limits_{i=1}^{n}\sum \limits_{j=1}^{n}\frac{1}{dis(i,j)}$ 然后这玩意可以用点分治求,合并子树用fft优化

 #include<bits/stdc++.h>
#define N 70050
#define LL long long
const int mod=,G1=,G2=(mod+)/G1;
#define cri const register int
using namespace std;
int a[N],b[N];
int n;
int he[N],ne[N],to[N],tot;
int sz[N],alsz,vis[N],rt;
inline void addedge(int x,int y){to[++tot]=y;ne[tot]=he[x];he[x]=tot;}
inline int dfssz(int g,int fa){
sz[g]=;int ret=;
for(int i=he[g],k;i;i=ne[i]){
if(to[i]==fa||vis[to[i]])continue;
k=dfssz(to[i],g);sz[g]+=sz[to[i]];ret=max(ret,k+);
}return ret;
}
inline void dfsrt(int g,int fa){
int hs=;
for(int i=he[g];i;i=ne[i]){
if(to[i]==fa||vis[to[i]])continue;
dfsrt(to[i],g);hs=max(hs,sz[to[i]]);
}
if(sz[g]>(alsz>>)&&hs<=(alsz>>))rt=g;
} inline int dfsdep(int g,int fa,int *a,int d){
++a[d];
for(int i=he[g];i;i=ne[i]){
if(to[i]==fa||vis[to[i]])continue;
dfsdep(to[i],g,a,d+);
}
} int r[N]; inline int qpow(int d,int z)
{
int ret=;
for(;z;z>>=,d=1ll*d*d%mod)
if(z&)ret=1ll*ret*d%mod;
return ret;
}
inline void ntt(int *a,cri n,cri tag){
int cnt=-;for(int i=n;i;i>>=,++cnt);
for(int i=;i<n;++i){
r[i]=(r[i>>]>>)|((i&)<<cnt);
if(r[i]>i)swap(a[i],a[r[i]]);
}
for(int i=;i<n;i<<=){
LL u=qpow(tag==?G1:G2,(mod-)/i/),w=,t;
for(int j=,I=i<<;j<n;j+=I,w=)
for(int k=;k<i;++k,w=w*u%mod)
t=a[j+k+i]*w%mod,a[j+k+i]=(a[j+k]-t+mod)%mod,(a[j+k]+=t)%=mod;
}
}
int c[N];int sum[N];
inline void work(int g)
{
int d=dfssz(g,)-,lim=;
vis[g]=;if(sz[g]==)return;
for(lim=;lim<=d+d;lim<<=);
for(register int i=;i<lim;++i)a[i]=b[i]=;
for(int i=he[g],d2,l2;i;i=ne[i]){
if(vis[to[i]])continue;dfsdep(to[i],g,a,);
for(d2=;a[d2];++d2)b[d2]+=a[d2];--d2;
for(l2=;l2<=d2+d2;l2<<=); ntt(a,l2,);
for(int j=;j<l2;++j)a[j]=1ll*a[j]*a[j]%mod;
ntt(a,l2,-); const LL iv=qpow(l2,mod-);
for(int j=;j<=d2+d2;++j)sum[j]-=iv*a[j]%mod;
for(int j=;j<l2;++j)a[j]=;
} for(int i=;i<=d;++i)sum[i]+=b[i]<<;
ntt(b,lim,);
for(int i=;i<lim;++i)b[i]=1ll*b[i]*b[i]%mod;
ntt(b,lim,-);
const LL iv=qpow(lim,mod-);
for(int i=;i<=d+d;++i)sum[i]+=iv*b[i]%mod; for(int i=he[g];i;i=ne[i]){
if(vis[to[i]])continue;
alsz=sz[to[i]],dfsrt(to[i],g),c[++c[]]=rt;
} }
int main()
{
// freopen("da.in","r",stdin);
scanf("%d",&n);
for(int i=,x,y;i<n;++i){
scanf("%d%d",&x,&y),++x,++y;
addedge(x,y),addedge(y,x);
}
dfssz(,);alsz=sz[];dfsrt(,);c[++c[]]=rt;
for(int i=;i<=c[];++i)work(c[i]);
double ans=;
for(int i=;i<n;++i)
{
// printf("i:%d sum:%d\n",i,sum[i]);
ans+=1.0*sum[i]/(i+1.0);
}
printf("%.4lf\n",ans+n);
}

T5:万径人踪灭

字符串与fft的结合,考虑以每个点为中心,用总共的减去连续的。发现只要求出以每个点为中心的对称的点对有多少个即可,对于中心mid,若l与r关于mid对称,

则mid=(l+r)>>1,然后这个东西就可以卷积了。对a和b分别卷积,就能求出以每个点为中心的对称的点对的个数,求连续的个数可以manacher也可以hash+二分

T6:序列统计

考察原根的用法。利用原根把乘法转化为加法,即将1~p-1中的每个数都表示为原根的k次方,原数相乘=新数相加,然后就可以ntt了

T7:求和

fft与斯特林数结合,个人感觉难想的点其实在于把j的枚举范围从i直接升到n,这样其实是去掉j对i的限制,同时不影响答案。

T8:染色

fft+二项式反演。首先化式子,$ \binom{m}{k}*\binom{n}{k*s}*\frac{(k*s)!}{x^{k}}*(m-k)^{n-k*s} $就得到了钦定k个的方案数,注意,是钦定,而不是至少。

然后利用二项式反演的至少形式,化成卷积式,就可以fft了。

T9:城市规划

次题考察分治fft,分治fft的形式:$f[i]=\sum\limits_{j=1}^{i}g[j]*f[i-j]$

 #include<bits/stdc++.h>
#define cri const register int
#define N 270050
#define LL long long
const int mod=,G1=,G2=(mod+)/G1;
using namespace std;
int n,f[N],g[N];
inline int qpow(int d,LL z){
int ret=;
for(;z;z>>=,d=1ll*d*d%mod)
if(z&)ret=1ll*ret*d%mod;
return ret;
}
int inc[N],inv[N];
inline void init(int n){
inc[]=inv[]=;
for(int i=;i<=n;++i)inc[i]=1ll*inc[i-]*i%mod;
inv[n]=qpow(inc[n],mod-);
for(int i=n-;i;--i)inv[i]=1ll*inv[i+]*(i+)%mod;
for(int i=;i<=n;++i)
g[i]=1ll*qpow(,1ll*i*(i-)>>)*inv[i]%mod;
}
inline void ntt(int *a,cri n,cri tag)
{
static int r[N],cnt;
cnt=-;for(int i=n;i;i>>=,++cnt);
for(int i=;i<n;++i){
r[i]=(r[i>>]>>)|((i&)<<cnt);
if(i>r[i])swap(a[i],a[r[i]]);
}
for(int i=;i<n;i<<=){
LL u=qpow(tag==?G1:G2,(mod-)/i/),w=,t;
for(int j=,I=i<<;j<n;j+=I,w=)
for(int k=;k<i;++k,(w*=u)%=mod)
t=w*a[j+k+i]%mod,a[j+k+i]=(a[j+k]-t+mod)%mod,(a[j+k]+=t)%=mod;
}
}
inline void solve(int l,int r){
if(l>n)return;
if(l==r){//printf("f[%d]=%d\n",l,f[l]);
if(l){
f[l]=1ll*f[l]*inc[l-]%mod;
f[l]=(1ll*g[l]*inc[l]%mod+0ll+mod-f[l])%mod;
f[l]=1ll*f[l]*inv[l-]%mod;
}
return;
}
static int ff[N],gg[N];
const int mid=l+r>>;
solve(l,mid); for(int i=l;i<=mid;++i)ff[i-l]=f[i],gg[i-l]=g[i-l];
for(int i=mid+;i<=r;++i)ff[i-l]=,gg[i-l]=g[i-l];//gg[r-l]=0;
ntt(ff,r-l+,);ntt(gg,r-l+,);
for(int i=;i<r-l+;++i)ff[i]=1ll*ff[i]*gg[i]%mod;
ntt(ff,r-l+,-);const LL iv=qpow(r-l+,mod-);
for(int i=mid+;i<=r;++i)(f[i]+=iv*ff[i-l]%mod)%=mod;
solve(mid+,r);
}
int main(){
scanf("%d",&n);init(n);
int lim;for(lim=;lim<=n;lim<<=);
solve(,lim-);
// for(int i=1;i<=n;++i)printf("%lld\n",1ll*f[i]*inc[i-1]%mod);
printf("%lld\n",1ll*f[n]*inc[n-]%mod);
return ;
}

板子

然而这题化式子好像也挺难的。。。

考虑用总共的减去不合法的。设f[i]为答案数组,g[i]为i个点随意组合的方案数,则g[i]=2n*(n-1)/2

考虑最后一个点加在了哪个联通块里面:$f[i]=g[i]-\sum\limits_{j=1}^{i-1}\binom{i-1}{j}g[i-j]*f[j]$就可以卷积了。

fft,ntt总结的更多相关文章

  1. FFT \ NTT总结(多项式的构造方法)

    前言.FFT  NTT 算法 网上有很多,这里不再赘述. 模板见我的代码库: FFT:戳我 NTT:戳我 正经向:FFT题目解题思路 \(FFT\)这个玩意不可能直接裸考的..... 其实一般\(FF ...

  2. [学习笔记&教程] 信号, 集合, 多项式, 以及各种卷积性变换 (FFT,NTT,FWT,FMT)

    目录 信号, 集合, 多项式, 以及卷积性变换 卷积 卷积性变换 傅里叶变换与信号 引入: 信号分析 变换的基础: 复数 傅里叶变换 离散傅里叶变换 FFT 与多项式 \(n\) 次单位复根 消去引理 ...

  3. FFT/NTT/MTT学习笔记

    FFT/NTT/MTT Tags:数学 作业部落 评论地址 前言 这是网上的优秀博客 并不建议初学者看我的博客,因为我也不是很了解FFT的具体原理 一.概述 两个多项式相乘,不用\(N^2\),通过\ ...

  4. FFT&NTT总结

    FFT&NTT总结 一些概念 \(DFT:\)离散傅里叶变换\(\rightarrow O(n^2)\)计算多项式卷积 \(FFT:\)快速傅里叶变换\(\rightarrow O(nlogn ...

  5. 快速构造FFT/NTT

    @(学习笔记)[FFT, NTT] 问题概述 给出两个次数为\(n\)的多项式\(A\)和\(B\), 要求在\(O(n \log n)\)内求出它们的卷积, 即对于结果\(C\)的每一项, 都有\[ ...

  6. FFT/NTT模板 既 HDU1402 A * B Problem Plus

    @(学习笔记)[FFT, NTT] Problem Description Calculate A * B. Input Each line will contain two integers A a ...

  7. FFT/NTT基础题总结

    在学各种数各种反演之前把以前做的$FFT$/$NTT$的题整理一遍 还请数论$dalao$口下留情 T1快速傅立叶之二 题目中要求求出 $c_k=\sum\limits_{i=k}^{n-1}a_i* ...

  8. $FFT/NTT/FWT$题单&简要题解

    打算写一个多项式总结. 虽然自己菜得太真实了. 好像四级标题太小了,下次写博客的时候再考虑一下. 模板 \(FFT\)模板 #include <iostream> #include < ...

  9. FFT&NTT数学解释

    FFT和NTT真是噩梦呢 既然被FFT和NTT坑够了,坑一下其他的人也未尝不可呢 前置知识 多项式基础知识 矩阵基础知识(之后会一直用矩阵表达) FFT:复数基础知识 NTT:模运算基础知识 单位根介 ...

  10. HDU-4609(FFT/NTT)

    HDU-4609(FFT/NTT) 题意: 给出n个木棒,现从中不重复地选出3根来,求能拼出三角形的概率. 计算合法概率容易出现重复,所以建议计算不合法方案数 枚举选出的最大边是哪条,然后考虑剩下两条 ...

随机推荐

  1. Kubernetes 学习笔记(一):基础概念

    个人笔记,仅本人查阅使用,不保证正确. 零.微服务 微服务架构专注于应用解耦合,通过将应用彻底地组件化和服务化,每个微服务只包含一个非常小的功能,比如权限管理.日志收集等等.由这一组微服务组合起来,提 ...

  2. Liar CodeForces - 822E (dp,后缀数组)

    大意: 给定串$s,t$, 给定整数$x$, 求判断$t$是否能划分为至多$x$段, 使这些段在$s$中按顺序,不交叉的出现. 设$dp_{i,j}$表示$s$匹配到$i$位, 划分了$j$段, 匹配 ...

  3. 记一次纯sqlite数据库的小项目开发经历

    sqlite有哪些坑 1.支持的数据量级:根据SQLite的官方提示:http://www.sqlite.org/limits.htmlSQLIte数据库最大支持128TiB(140 terabyte ...

  4. Consul基本使用

    原文: Consul基本使用 date: 2019-05-13 17:01:37 前言 官网介绍Consul是一个分布式服务网格(Service Mesh)解决方案... 而我目前的理解是提供了分布式 ...

  5. kafka的生产者配置以及发送信息的三种方式

    1.Fire-and-forget 这种方式是不管发送成功与否,客户端都会返回成功.尽管大多数的时候Kafka 在发送失败后,会自己重新自动再一次发送消息,但是也会存在丢失消息的风险 Producer ...

  6. SQL case when 遇到null值

    case  when f.FPH is  NULL then a.HSJE else f.KPHSJE  end    yes case f.FPH  when   NULL then a.HSJE ...

  7. extjs6 创建工程和打包发布

    准备工作: 下载extjs6的开发包,我这里是试验版:ext-6.6.0-trial.zip.解压到某个目录,我这里解压到:D:\tools\about-ext\ext-6.6.0-trial 目录下 ...

  8. Google hacking 语法

    a b c 自动对词进行拆分匹配 拆分标准 空格 "a b c " 把a b c 当成一个整体去查 " a*b" *通配符 里面是一个或者多个 以a开头 b结尾 ...

  9. 优雅的处理vue注册全局组件

    使用情景: 有频繁使用的组件 需要进行全局注册 可以将这些组件都放在components下同一个文件夹下,在此文件夹中建立 一个js文件 代码如下: import Vue from 'vue'; // ...

  10. AJAX学习笔记——JSON

    JSON基本概念 1.JSON : JavaScript对象表示法( JavaScript Object Notation ) 2.JSON是存储和交换文本信息的语法,类似XML.它采用键值对的方式来 ...