bzoj2194 快速傅立叶之二
生活随笔
收集整理的這篇文章主要介紹了
bzoj2194 快速傅立叶之二
小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
2194: 快速傅立葉之二
Time Limit:?10 Sec??Memory Limit:?259 MBSubmit:?1730??Solved:?1026
[Submit][Status][Discuss]
Description
請(qǐng)計(jì)算C[k]=sigma(a[i]*b[i-k]) 其中 k < = i < n ,并且有 n < = 10 ^ 5。 a,b中的元素均為小于等于100的非負(fù)整數(shù)。
Input
第一行一個(gè)整數(shù)N,接下來(lái)N行,第i+2..i+N-1行,每行兩個(gè)數(shù),依次表示a[i],b[i] (0 < = i < N)。Output
輸出N行,每行一個(gè)整數(shù),第i行輸出C[i-1]。
Sample Input
53 1
2 4
1 1
2 4
1 4
Sample Output
2412
10
6
1 分析:很顯然,這道題要用FFT來(lái)做,但是題目所給的式子并不是一個(gè)標(biāo)準(zhǔn)的卷積的形式,需要進(jìn)行變形. 一般而言,能用FFT求的式子c[k] = a[i] * b[j], i + j是一個(gè)只與k有關(guān)的式子,其它的都是常數(shù)項(xiàng).? 對(duì)于這道題,把bi變成b_n-i-1 那么ck = ai*b_i - k = ai * b_n - (i - k) - 1 = ai * b_n -i - 1 + k.? a和b的下標(biāo)加起來(lái)恰好是n + k,n是常數(shù),滿足做fft的要求. 最后c數(shù)組的值要整體向后移k位.?
#include <cstdio> #include <cmath> #include <cstring> #include <iostream> #include <algorithm>using namespace std;const int maxn = (1 << 18) + 5; const double pai = acos(-1.0); int n,a[maxn],b[maxn],len;struct node {double real, imag;node(double real = 0.0, double imag = 0.0){this->real = real, this->imag = imag;}node operator - (const node&elem) const{return node(this->real - elem.real, this->imag - elem.imag);}node operator + (const node&elem) const{return node(this->real + elem.real, this->imag + elem.imag);}node operator * (const node&elem) const{return node(this->real * elem.real - this->imag * elem.imag, this->real * elem.imag + this->imag * elem.real);}void set(double real = 0.0, double imag = 0.0){this->real = real, this->imag = imag;} } A[maxn],B[maxn];void pre() {for (int i = 0; i < n; i++)scanf("%d%d",&a[i],&b[i]);len = 1;while (len < (n << 1))len <<= 1;for (int i = 0; i < n; i++)A[i].set(a[i],0),B[i].set(b[n - i - 1],0);for (int i = n; i < len; i++)A[i].set(),B[i].set(); }void Swap(node &a,node &b) {node temp = a;a = b;b = temp; }void zhuan(node *y) {for (int i = 1,j = len >> 1,k; i < len - 1; i++){if (i < j)Swap(y[i],y[j]);k = len >> 1;while (j >= k){j -= k;k >>= 1;}if (j < k)j += k;} }void FFT(node *y,int op) {zhuan(y);for (int h = 2; h <= len; h <<= 1){node temp(cos(op * pai * 2 / h),sin(op * pai * 2 / h));for (int i = 0; i < len; i += h){node W(1,0);for (int j = i; j < i + h / 2; j++){node u = y[j];node v = W * y[j + h / 2];y[j] = u + v;y[j + h / 2] = u - v;W = W * temp;}}}if (op == -1)for (int i = 0; i < len; i++)y[i].real /= len; }void solve(node *A,node *B) {FFT(A,1);FFT(B,1);for (int i = 0; i < len; i++)A[i] = A[i] * B[i];FFT(A,-1); }int main() {scanf("%d",&n);pre();solve(A,B);for (int i = n - 1; i < 2 * n - 1; i++)printf("%d\n",(int)(A[i].real + 0.5));return 0; }
?
轉(zhuǎn)載于:https://www.cnblogs.com/zbtrs/p/8639793.html
總結(jié)
以上是生活随笔為你收集整理的bzoj2194 快速傅立叶之二的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: Linux日常运维管理技巧(四)文件同步
- 下一篇: Web安全之点击劫持(ClickJack