MTT学习小记
这是个毒瘤题才有的毒瘤东西……奶一口NOI不考
拆系数FFT:
考虑做NTT时模数不是NTT模数(\(2^a*b+1\))怎么办?
很容易想到拆次数FFT。
比如说现在求\(a*b\),设\(m=\sqrt mo(2^{15})\)
那么把\(a[i]\)拆成\(a0[i]+a1[i]*m\),b[i]拆成\(b0[i]+b1[i]*m\)
那么\(a[i]*b[j]=a0[i]*b0[j]+(a0[i]*b1[j]+a1[i]*b0[j])*m+(a1[i]*b1[j])*m^2\)
由于\(a0,b1,b0,b1\)的大小都不到,所以FFT不会爆精度。
那么这个最好也需要4(正)+3(逆)=7,复杂度不能接受。
DFT:
一开始要做4次DFT,我们两两一起做。
假设现在有两个序列A、B,要求DFT(A)和DFT(B)
设\(P=A+B*i,Q=A-B*i\)
只用做P的DFT,便可得到Q的DFT。
\(DFT(Q)[n-i]=conj(DFT(P)[i])\),\(conj\)为共轭,就是把虚部系数取反。
证明:
\(conj(DFT(P)[i])\)
\(=conj(\sum_{j=0}^{n-1}w_n^{ji}*(A[i]+B[i]*\sqrt{-1})\)
\(=\sum_{j=0}^{n-1}conj(w_n^{ji})*conj(A[i]+B[i]*\sqrt{-1})\)
\(=\sum_{j=0}^{n-1}w_n^{-ij}*(A[i]-B[i]*\sqrt{-1})\)
\(=DFT(Q)[n-i]\)
这样求出了\(DFT(P),DFT(Q)\)
那么\(DFT(A)=(DFT(P)+DFT(Q))*({1\over2},0),\\DFT(B)=(DFT(P)-DFT(Q))*(-1)*(0, {1\over2})\)
这个东西显然有一个条件是\(A、B\)只能实部有值,不然会混乱了无法提出来的。
IDFT:
接下来是IDFT,同样的可以两个 一起做。
如果有\(A、B\),都只有实部有值,设\(C=DFT(A)+i*DFT(B)\)
显然\(IDFT(C)\)的实部就是A,虚部就是B
这样我们就用四次DFT完成啦!
Code:
#include<bits/stdc++.h>
#define fo(i, x, y) for(int i = x, B = y; i <= B; i ++)
#define ff(i, x, y) for(int i = x, B = y; i < B; i ++)
#define fd(i, x, y) for(int i = x, B = y; i >= B; i --)
#define ll long long
#define pp printf
#define hh pp("\n")
#define db double
using namespace std;
const db pi = acos(-1);
const int mo = 1e9 + 7;
struct P {
db x, y;
P(db _x = 0, db _y = 0) { x = _x, y = _y;}
P operator + (P b) { return P(x + b.x, y + b.y);}
P operator - (P b){ return P(x - b.x, y - b.y);}
P operator * (P b) { return P(x * b.x - y * b.y, x * b.y + y * b.x);}
};
const int nm = 1 << 18;
P w[nm]; int r[nm];
P c0[nm], c1[nm], c2[nm], c3[nm];
void dft(P *a, int n) {
ff(i, 0, n) {
r[i] = r[i / 2] / 2 + (i & 1) * (n / 2);
if(i < r[i]) swap(a[i], a[r[i]]);
} P b;
for(int i = 1; i < n; i *= 2) for(int j = 0; j < n; j += 2 * i)
ff(k, 0, i) b = a[i + j + k] * w[i + k], a[i + j + k] = a[j + k] - b, a[j + k] = a[j + k] + b;
}
void rev(P *a, int n) {
reverse(a + 1, a + n);
ff(i, 0, n) a[i].x /= n, a[i].y /= n;
}
P conj(P a) { return P(a.x, -a.y);}
void fft(ll *a, ll *b, int n) {
#define qz(x) ((ll) round(x))
// ff(i, 0, n) c0[i] = P(a[i], 0), c1[i] = P(b[i], 0);
// dft(c0, n); dft(c1, n);
// ff(i, 0, n) c0[i] = c0[i] * c1[i];
// dft(c0, n); rev(c0, n);
// ff(i, 0, n) a[i] = qz(c0[i].x);
ff(i, 0, n) c0[i] = P(a[i] & 32767, a[i] >> 15), c1[i] = P(b[i] & 32767, b[i] >> 15);
dft(c0, n); dft(c1, n);
ff(i, 0, n) {
P k, d0, d1, d2, d3;
int j = (n - i) & (n - 1);
k = conj(c0[j]);
d0 = (k + c0[i]) * P(0.5, 0);
d1 = (k - c0[i]) * P(0, 0.5);
k = conj(c1[j]);
d2 = (k + c1[i]) * P(0.5, 0);
d3 = (k - c1[i]) * P(0, 0.5);
c2[i] = d0 * d2 + d1 * d3 * P(0, 1);
c3[i] = d0 * d3 + d1 * d2;
}
dft(c2, n); dft(c3, n); rev(c2, n); rev(c3, n);
ff(i, 0, n) {
a[i] = qz(c2[i].x) + (qz(c2[i].y) % mo << 30) + (qz(c3[i].x) % mo << 15);
a[i] %= mo;
}
}
ll a[nm], b[nm];
int main() {
for(int i = 1; i < nm; i *= 2) ff(j, 0, i)
w[i + j] = P(cos(pi * j / i), sin(pi * j / i));
fo(i, 0, 15) a[i] = b[i] = mo - 1;
fft(a, b, 32);
ff(i, 0, 32) pp("%lld ", a[i]);
}
MTT学习小记的更多相关文章
- mongodb入门学习小记
Mongodb 简单入门(个人学习小记) 1.安装并注册成服务:(示例) E:\DevTools\mongodb3.2.6\bin>mongod.exe --bind_ip 127.0.0.1 ...
- javascript学习小记(一)
大四了,课少了许多,突然之间就不知道学什么啦.整天在宿舍混着日子,很想学习就是感觉没有一点头绪,昨天看了电影激战.这种纠结的情绪让我都有点喘不上气啦!一点要找点事情干了,所以决定找个东西开始学习.那就 ...
- js 正则学习小记之匹配字符串
原文:js 正则学习小记之匹配字符串 今天看了第5章几个例子,有点收获,记录下来当作回顾也当作分享. 关于匹配字符串问题,有很多种类型,今天讨论 js 代码里的字符串匹配.(因为我想学完之后写个语法高 ...
- js 正则学习小记之左最长规则
原文:js 正则学习小记之左最长规则 昨天我在判断正则引擎用到的方法是用 /nfa|nfa not/ 去匹配 "nfa not",得到的结果是 'nfa'.其实我们的本意是想得到整 ...
- js 正则学习小记之NFA引擎
原文:js 正则学习小记之NFA引擎 之前一直认为自己正则还不错,在看 次碳酸钴,Barret Lee 等大神都把正则玩的出神入化后发现我只是个战五渣. 求抱大腿,求大神调教. 之前大致有个印象,正 ...
- js 正则学习小记之匹配字符串优化篇
原文:js 正则学习小记之匹配字符串优化篇 昨天在<js 正则学习小记之匹配字符串>谈到 个字符,除了第一个 个,只有 个转义( 个字符),所以 次,只有 次成功.这 次匹配失败,需要回溯 ...
- CSS学习小记
搜狗主页页面CSS学习小记 1.边框的处理 要形成上图所示的布局效果,即,点选后,导航下面的边框不显示而其他的边框形成平滑的形状.相对于把导航的下面边框取消然后用空白覆盖掉下面搜索栏的边框比较而言 ...
- Gcd&Exgcd算法学习小记
Preface 对于许多数论问题,都需要涉及到Gcd,求解Gcd,常常使用欧几里得算法,以前也只是背下来,没有真正了解并证明过. 对于许多求解问题,可以列出贝祖方程:ax+by=Gcd(a,b),用E ...
- logstash 学习小记
logstash 学习小记 标签(空格分隔): 日志收集 Introduce Logstash is a tool for managing events and logs. You can use ...
随机推荐
- Coin Slider
题目描述 You are playing a coin puzzle. The rule of this puzzle is as follows: There are N coins on a ta ...
- master挂了的话pm2怎么处理 使用pm2方便开启node集群模式
本文为转载 Introduction As you would probably know, Node.js is a platform built on Chrome's JavaScript ru ...
- vue 多选框 checkbox 父到子传值
vue多选功能, 修改时选中的状态不能从当前组件中得到,从父组件中传过来. 这里 新增和修改封装了一个组件,在点击确定按钮后,会发送新增或修改请求,重新渲染页面.但是在点击[新增]/ [修改]按钮时, ...
- Vue学习笔记【12】——过滤器
概念:Vue.js 允许你自定义过滤器,可被用作一些常见的文本格式化.过滤器可以用在两个地方:mustache 插值和 v-bind 表达式.过滤器应该被添加在 JavaScript 表达式的尾部,由 ...
- Linux系统上安装MySQL 5.5prm
http://www.cnblogs.com/sunson/articles/2172086.html
- 【LeetCode 4】寻找两个有序数组的中位数
题目链接 [题解] 假设在两个有序的序列中找第k小的数字. 那么我们先定位第一个序列中的第k/2个数字(不足则取最边上的那个数字)记下标为i1 然后定位第二个序列中的第k/2个数字(同样不足则取最边上 ...
- JVM内存分为哪几部分?各个部分的作用是什么?
JVM内存区域分为五个部分,分别是堆,方法区,虚拟机栈,本地方法栈,程序计数器. 堆. 堆是Java对象的存储区域,任何用new字段分配的Java对象实例和数组,都被分配在堆上,Java堆可使用-Xm ...
- 原生js 与 jQuery对比
1.原生JS与jQuery操作DOM对比 : https://www.cnblogs.com/QianBoy/p/7868379.html 2.比较jQuery与JavaScript的不同功能实 ...
- (转)MySQL安装及配置指南
转:http://wiki.ubuntu.org.cn/MySQL%E5%AE%89%E8%A3%85%E6%8C%87%E5%8D%97 安装MySQL sudo apt-get install m ...
- php开发面试题---php面向对象详解(对象的主要三个特性)
php开发面试题---php面向对象详解(对象的主要三个特性) 一.总结 一句话总结: 对象的行为:可以对 对象施加那些操作,开灯,关灯就是行为. 对象的形态:当施加那些方法是对象如何响应,颜色,尺寸 ...