fft练习

数学相关一直都好弱啊>_<

窝这个月要补一补数学啦, 先从基础的fft补起吧!

现在做了 道。

窝的fft 模板 (bzoj 2179)

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstring>
 4 #include <cmath>
 5 #include <algorithm>
 6 #define MAXN 200005
 7 #define PI M_PI
 8 using namespace std;
 9 struct CP{
10     double x, y;
11     CP(){}
12     CP(double x, double y) : x(x), y(y) {}
13     inline CP operator+ (CP b) {return CP(x+b.x, y+b.y);}
14     inline CP operator- (CP b) {return CP(x-b.x, y-b.y);}
15     inline CP operator* (CP b) {return CP(x*b.x-y*b.y, x*b.y+y*b.x);}
16 }a[MAXN], b[MAXN], A[MAXN], x, y;
17 int n, N, l, dig[MAXN], ans[MAXN];
18 char s1[MAXN], s2[MAXN];
19 inline void dft(CP *a, int n, int f){
20     for(int i = 0; i < n; i ++) A[i] = a[dig[i]];
21     for(int i = 0; i < n; i ++) a[i] = A[i];
22     for(int i = 2; i <= n; i <<= 1){
23         CP wn(cos(2*PI/i), f*sin(2*PI/i));
24         for(int k = 0; k < n; k += i){
25             CP w(1, 0);
26             for(int j = 0; j < i/2; j ++) x = a[k+j], y = w*a[k+j+i/2], a[k+j]=x+y, a[k+j+i/2] = x-y, w = w*wn;
27         }
28     }
29 }
30 int main(){
31     scanf("%d%s%s", &n, s1, s2);
32     for(int i = 0; i < n; i ++) a[i].x = s1[n-i-1]-‘0‘, b[i].x = s2[n-i-1]-‘0‘;
33     for(N = 1, l = 0; N < n; N <<= 1, l ++); N <<= 1, l ++;
34     for(int i = 0; i < N; i ++){
35         int ret = 0, p = i;
36         for(int j = 1; j <= l; j ++) ret <<= 1, ret += (p&1), p >>= 1;
37         dig[i] = ret;
38     }
39     dft(a, N, 1), dft(b, N, 1);
40     for(int i = 0; i < N; i ++) a[i] = a[i]*b[i];
41     dft(a, N, -1);
42     for(int i = 0; i < N; i ++) ans[i] = (int)(a[i].x / N + 0.5);
43     for(int i = 0; i < N; i ++) ans[i+1] += ans[i]/10, ans[i] %= 10;
44     l = N; while(l > 1 && ans[l-1] == 0) l --;
45     for(int i = l-1; i >= 0; i --) printf("%d", ans[i]); cout << endl;
46     return 0;
47 }

BZOJ 2194

之前做过的啦,求 c_k = Σ(a_i * b_(i-k))  (k <= i)

标准的差积形式是 i + j 一定, 现在的式子要求 i - j 一定, 容易想到把所有b的下标都乘以-1原式即转化为i+j一定了, 为了方便处理可以把所有b再加上n使得下标为非负数,即把b_i 变为 b_(n-i) 。

tips: 卷积的形式并不一定只是 k = i+j, 还有可能是 k = i-j 或者 …………

bzoj 3527: [Zjoi2014]力

之前做过的啦。 不打式子了, 是个人都会把qi乘进去, 然后原式就变成了求 E_i = Σqj/((i-j)^2) (j<i) - Σqj/((i-j)^2) (j>i)

我第一次做的时候并没有看出来这是个卷积QAQ 蠢死了QAQ

我们可以设 一个 函数 f(x) = q_x, g(x) = 1/(x^2), 然后那个式子的前一项不就是 f 和 g 的卷积了吗! 第二个式子是 当 i-j一定时候的情况, 那不就是上一题 bzoj 2194了吗,,,,然后就没了。

tips:不要拘泥于已有的数列,可以根据题目自己构造出新的函数, 需要求 F_i = Σ( f(j) 乘或除以 g(i±j) ) 的时候很有可能是卷积!!!看到 j 和 i±j 这类的关键词就应该往这边多想一想。

BZOJ 3771 Triple

之前做过的啦。给定n个物品,可以用一个/两个/三个不同的物品凑出不同的价值,求每种价值有多少种拼凑方案(顺序不同算一种) (题目大意来自popoqqq

自己还是没有想到QAQ

这个要构建一个母函数。初步地感受母函数的应用:如果我们可以快速地计算出一次操作后每种效果有多少种产生方案(0/1),并且多次操作的效果是可以累加的,那么在用fft优化以后(效果的累加不就是卷积吗)可以比较快速地(k*nlogn)计算出k次操作后每种效果有多少种产生方案 (怎么觉得我在说的是用快速幂优化的矩阵乘法啊。。。。。)感觉的确和矩乘有点像, 不过矩乘的每次操作的状态是一个二维的数组, 因为在不同的点可以进行的操作不同, 但是 母函数只需要求出一个一维数组, 因为在应用母函数的时候当前状态 并不会影响下一步的操作

(以上皆是窝自己的口胡,等我读完具体数学的 "生成函数" 一章后再来总结吧QAQ)

tips: 见上

BZOJ 3160 万径人踪灭

给出一个只含有a和b的字符串, 求有多少个至少有一个断点(即不完全连续)的回文子序列,要求子序列选出来的每一个的位置同样必须关于任意一个位置或中缝对称。

考虑以每一个点i为中间的点所组成的符合要求的子序列,对于每一个j, 如果 s[i-j] == s[i+j] 则可以把这对字符加到子序列里, 当然也可以不加, 显然对于不同的j, 每一对字符是相互独立的, 所以以i为中点的贡献就是 2^(s[i-j]==s[i+j]的数量), 注意因为子序列不可以完全连续所以还要再减去一个可以直接manachar求出来的完全连续的回文串数量。 所以现在唯一剩下的问题就是对于每一个i, Σ (s[i-j] == s[i+j]), 因为只有a, b两种字符, 显然可以拆开来算, 设数组A使得 A_i = (s[i] == ‘a‘), 则字符a对于以i为中心贡献就是 Σ (s[j]*s[2*i-j]) , 这个显然就是一个卷积啦。

hdu 4509 3-idiot

给你三根线段, 问你有多少种可以组成三角形的方法。

做过bzoj3771后这题就是一眼题了QAQ 类似地,对于边长建出一个生成函数然后卷积一次算出由两条边组成的长度和为x的线段组有多少组然后再扫一遍第三条边就可以了。

时间: 2024-10-09 20:23:19

fft练习的相关文章

XJTUOJ wmq的A&#215;B Problem FFT

wmq的A×B Problem 发布时间: 2017年4月9日 17:06   最后更新: 2017年4月9日 17:07   时间限制: 3000ms   内存限制: 512M 描述 这是一个非常简单的问题. wmq如今开始学习乘法了!他为了训练自己的乘法计算能力,写出了n个整数,并且对每两个数a,b都求出了它们的乘积a×b.现在他想知道,在求出的n(n−1)2个乘积中,除以给定的质数m余数为k(0≤k<m)的有多少个. 输入 第一行为测试数据的组数. 对于每组测试数据,第一行为2个正整数n,

对AM信号FFT的matlab仿真

普通调幅波AM的频谱,大信号包络检波频谱分析 u(t)=Ucm(1+macos ?t)cos ?ct ma称为调幅系数 它的频谱由载波,上下边频组成 , 包络检波中二极管截去负半周再用电容低通滤波,可以得到基带信号,那么,截去负半周后的AM信号必定包含基带信号的频谱.我们可以通过matlab来验证. %已知基带信号为1hz,载波为64hz,调制系数ma=0.3,采样频率1024hz,FFT变换区间N为2048 clear; fs=1024; f=1; %1hz基带信号 fc=64; %64hz载

多项式FFT相关模板

自己码了一个模板...有点辛苦...常数十分大,小心使用 #include <iostream> #include <stdio.h> #include <math.h> #include <string.h> #include <time.h> #include <stdlib.h> #include <algorithm> #include <vector> using namespace std; #de

多项式艺术:浅谈FFT和NTT算法(未完待续)

什么是多项式? 百度百科说:“由若干个单项式相加组成的代数式叫做多项式.多项式中每个单项式叫做多项式的项,这些单项式中的最高次数,就是这个多项式的次数.” 也就是说,形如的式子,就叫做多项式.这样的式子,也能写作.很显然,多项式加上(或是减上)多项式也是多项式,复杂度是的.但是,如果多项式想要乘上一个多项式,那么也可以,最简单的方法却是的. 不过,FFT算法会告诉你,就够了. 多项式乘法 我们说的,多项式想要乘上一个多项式,那就是多项式乘法,人称“卷积”.我们方才所看到的,被称为多项式的“系数表

FFT模板(From MG)

1 #include<cstdio> 2 #include<cmath> 3 #include<algorithm> 4 using namespace std; 5 struct cp{double x,y;}; 6 int n1,n2,n,m; 7 double pi=acos(-1); 8 cp a[500010],b[500010],cur[500010]; 9 cp operator *(cp x,cp y){return (cp){x.x*y.x-x.y*y

Bzoj2179 FFT快速傅立叶

Time Limit: 10 Sec  Memory Limit: 259 MBSubmit: 3079  Solved: 1581 Description 给出两个n位10进制整数x和y,你需要计算x*y. Input 第一行一个正整数n. 第二行描述一个位数为n的正整数x. 第三行描述一个位数为n的正整数y. Output 输出一行,即x*y的结果. Sample Input 1 3 4 Sample Output 12 数据范围: n<=60000 HINT Source FFT FFT真

BZOJ 2194 快速傅立叶之二 ——FFT

[题目分析] 咦,这不是卷积裸题. 敲敲敲,结果样例也没过. 看看看,卧槽i和k怎么反了. 艹艹艹,把B数组取个反. 靠靠靠,怎么全是零. 算算算,最终的取值范围算错了. 交交交,总算是A掉了. [代码] #include <cstdio> #include <cstring> #include <cmath> #include <cstdlib> #include <map> #include <set> #include <

BZOJ 2179 FFT快速傅立叶 ——FFT

[题目分析] 快速傅里叶变换用于高精度乘法. 其实本质就是循环卷积的计算,也就是多项式的乘法. 两次蝴蝶变换. 二进制取反化递归为迭代. 单位根的巧妙取值,是的复杂度成为了nlogn 范德蒙矩阵计算逆矩阵又减轻了拉格朗日插值法的复杂度. 十分神奇. [代码] #include <cstdio> #include <cstring> #include <cstdlib> #include <cmath> #include <set> #includ

MATLAB中fft

一般的fft需要将点数补成2的整数次幂,MATLAB中有fft函数,输入N点序列则输出也是N点序列,其中N不一定为2的整数次幂.所以会疑惑MATLAB做的fft和N点序列对应的dft是否一样.经过验证,MATLAB中对N点序列做fft的结果与N点dft的结果是完全一样的,没有对N点序列进行补0后再做操作. 下面是MATLAB代码和结果. n = 0: 49; A = 444.128; a = 50 * sqrt(2.0) * pi; w0 = 50 * sqrt(2.0) * pi; T = 0

FFT及NTT学习

贴上学习FFT和NTT的资料,以后再补题吧 http://blog.miskcoo.com/2015/04/polynomial-multiplication-and-fast-fourier-transform#i-15 http://blog.csdn.net/acdreamers/article/details/39005227 http://blog.csdn.net/acdreamers/article/details/39026505