炫酷反演魔术 魔术揭秘
来源:互联网 发布:程序员编程动漫 编辑:程序博客网 时间:2024/04/30 12:34
刚才的标题是唬人的…
请允许我先丢个链接,然后开始扯淡.
开场
vfk老师在这份课件中深入浅出地讲解了各种OI中常用的反演,本蒟蒻表示并没有完全看懂(尤其是对于矩阵的一部分知识不是非常熟悉),而且由于网上关于反演的资料除了莫比乌斯反演之外非常少,所以本蒟蒻在这里只是谈谈个人对反演的理解,如果出现了错误还请各路神犇不吝赐教.
还有就是课件中的推导已经写得非常漂亮了,我也没必要在这里再自己敲一遍(所以写这篇博客的目的何在?),有些地方还是直接”抛结论跑”好了.
揭秘
反演的思路是用未知量表示已知量,然后反过来推出未知量的表达式.下面我们默认表示已知量,表示未知量.
课件中介绍了二项式反演,莫比乌斯反演,子集反演等等,这些反演都与容斥原理有着密不可分的关系,就是说都可以用容斥来偏”意识流”地理解.但是不管怎么说,用反演来推导显得比较有说(zhuang)服(bi)力(fan).
推导反演的过程,就是”找到了一个if语句,说了一句废话,代进去搞搞居然就凑出来了个”.当然这其中需要很多技巧,可以通过看课件中的推导来体会.
二项式反演
推导的if语句是.
说的废话是.
莫比乌斯反演
一个方向:
另一个方向:
说实话我并不知道反方向的是怎么推的,但是结论非常好记.
if语句:.
废话:.
子集反演
一个方向:
另一个方向:
还是只会推正方向的…
if语句:.
废话:.
话说从这里开始变量名就有点奇怪了呢...
这个推导和二项式反演的推导非常相似.
实际运用时,这个东西可以用高维前缀和的写法来做,具体看下面的”卷积”部分.
离散傅里叶变换
这个东西实质上也是反演…但是我并不会用反演推…
给的if语句是.
然而我并不知道该说什么废话…
不过课件里那个”又一道经典题”是可以用这个if语句推的.
or卷积
给定,求:
关于这个名称应该没有正规的定义吧…似乎这个和下面的那个卷积都应该是”子集卷积”?还是看个人理解吧,我比较偏向于专门把下面的那个卷积称为”子集卷积”.
不管怎样,这个卷积是子集反演的一个经典应用.
令,类似地定义,可以推导出,求出后用子集反演求出.
具体实现时,直接略无脑地用高维前缀和正着倒着搞就可以实现子集反演了,复杂度是.
另外,卷积可以直接先把集合取补集转化成卷积来做.
Code
void or_conv(){ rep(i,0,n)rep(j,1,1<<n)if(j&1<<i){ A[j]+=A[j^1<<i]; B[j]+=B[j^1<<i]; } rep(i,0,1<<n)C[i]=A[i]*B[i]; rep(i,0,n)rep(j,1,1<<n)if(j&1<<i) C[j]-=C[j^1<<i];}
子集卷积
给定,求:
[Math Processing Error]
这个…似乎课件上的推导有些问题(当然很有可能是我没看懂),这里良心地写一下我的推法.
如果直接用交集和并集的限制是推不出来的,我们必须再加一个维度.
令[Math Processing Error],
还有[Math Processing Error].
那么:
然后再用子集反演,可以推出:
最终答案就是.
这样复杂度就可以做到了.
但是直接暴力做,复杂度是,凭借极小的常数在时仍可以碾压标程….
Code
const int N=17,M=1<<N;int n,bitcnt[M],A[M],B[M],C[M],sum_A[N+1][M],sum_B[N+1][M],sum_C[N+1][M];inline void init(){ rep(i,1,M)bitcnt[i]=bitcnt[i>>1]+(i&1);}void conv(){ rep(i,0,n+1)rep(j,0,1<<n){ if(i==bitcnt[j]){ sum_A[i][j]=A[j]; sum_B[i][j]=B[j]; } else sum_A[i][j]=sum_B[i][j]=0; } rep(i,0,n)rep(j,1,1<<n)if(j&1<<i)rep(k,0,bitcnt[j]){ mod_add(sum_A[k][j],sum_A[k][j^1<<i]); mod_add(sum_B[k][j],sum_B[k][j^1<<i]); } rep(i,0,n+1)rep(j,0,1<<n){ sum_C[i][j]=0; rep(k,0,i+1)sum_C[i][j]=(sum_C[i][j]+1ll*sum_A[k][j]*sum_B[i-k][j])%mod; } rep(i,0,n)rep(j,1,1<<n)if(j&1<<i)rep(k,0,n+1) mod_minus(sum_C[k][j],sum_C[k][j^1<<i]); rep(i,0,1<<n)C[i]=sum_C[bitcnt[i]][i];}
收场
妈呀最怕这种时候要我总结点什么了!
大概我对反演的理解也就是这些了…
我觉得学习反演,不应该只记个结论,中间的推导过程也是很有价值的.
那就先这样吧.
- 炫酷反演魔术 魔术揭秘
- 魔术
- 魔术
- 魔术
- 大卫.科波菲尔魔术揭秘(爆笑)
- 刘谦2010春晚魔术大揭秘
- 网友各显神通 揭秘刘谦魔术
- 【魔术】硬币魔术
- classloader魔术
- 橡皮筋魔术
- 魔术引号
- 魔术符号
- 魔术数
- 魔术方法
- 魔术方法:
- 数字魔术
- 数字魔术
- 魔术索引
- hibernate4 could not initialize proxy - no Session
- 预处理找到前N个质数
- php单元测试的优缺点
- Linux 进程学习(四)------ sigaction 函数
- Expression: _BLOCK_TYPE_IS_VALID(pHead->nBlockUse)
- 炫酷反演魔术 魔术揭秘
- java集合大家族之总结
- Myeclipse 手动安装Velocity插件
- logback日志管理配置
- Android gradle 自动签名
- 高逼格的block(链式编程思想 )
- 直接在服务器与客户端之间传输对象
- HTML5高级程序设计 test1 (与dojo和原生js的对比)
- Mysql学习总结(31)——MySql使用建议,尽量避免这些问题