生活随笔
收集整理的這篇文章主要介紹了
P4721 【模板】分治 FFT
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
傳送門
文章目錄
題意:
思路:
寫一下式子,發現每個fif_ifi?只有左邊的fff對他有影響,所以考慮分治FFTFFTFFT來解決這個問題。
先遞歸左邊,讓后計算對右邊貢獻,再遞歸右邊。
式子化簡一下就是fi=∑j=lmidfj?gi?jf_i=\sum_{j=l}^{mid}f_j*g_{i-j}fi?=∑j=lmid?fj??gi?j?,直接寫就好,注意卡常。。如果偷懶直接長度為nnn的乘起來會TTT很多點,所以需要偏移一下。
#include<cstdio>
#include<iostream>
#include<string>
#include<cstring>
#include<map>
#include<cmath>
#include<cctype>
#include<vector>
#include<set>
#include<queue>
#include<algorithm>
#include<sstream>
#include<ctime>
#include<cstdlib>
#include<random>
#include<cassert>
#define X first
#define Y second
#define R (u<<1|1)
#define pb push_back
#define mk make_pair
#define Mid ((tr[u].l+tr[u].r)>>1)
#define Len(u) (tr[u].r-tr[u].l+1)
#define random(a,b) ((a)+rand()%((b)-(a)+1))
#define db puts("---")
using namespace std
;
typedef long long LL
;
typedef unsigned long long ULL
;
typedef pair
<int,int> PII
;const int N
=4000010,mod
=998244353,INF
=0x3f3f3f3f;
const double eps
=1e-6;int n
;
LL g
[N
],f
[N
];
LL a
[N
], b
[N
];
struct NTT {int P
= 998244353, G
= 3, Gi
= 332748118;int n
, m
, limit
= 1, L
, r
[N
];LL qmi
[2][N
];inline LL
fastpow(LL a
, LL k
) {LL base
= 1;while(k
) {if(k
& 1) base
= (base
* a
) % P
;a
= (a
* a
) % P
;k
>>= 1;}return base
% P
;}inline void ntt(LL
*A
, int type
) {for(int i
= 0; i
< limit
; i
++) if(i
< r
[i
]) swap(A
[i
], A
[r
[i
]]);for(int mid
= 1; mid
< limit
; mid
<<= 1) { LL Wn
=qmi
[type
==1? 1:0][mid
];for(int j
= 0; j
< limit
; j
+= (mid
<< 1)) {LL w
= 1;for(int k
= 0; k
< mid
; k
++, w
= (w
* Wn
) % P
) {int x
= A
[j
+ k
], y
= w
* A
[j
+ k
+ mid
] % P
;A
[j
+ k
] = (x
+ y
) % P
,A
[j
+ k
+ mid
] = (x
- y
+ P
) % P
;}}}}void init_qmi() {for(int mid
=1;mid
<=4e5;mid
<<=1) {qmi
[1][mid
]=fastpow(G
,(P
- 1) / (mid
<< 1));qmi
[0][mid
]=fastpow(Gi
,(P
- 1) / (mid
<< 1));}}void init(int n
,int m
) {limit
=1; L
=0;while(limit
<= m
+ n
) limit
<<= 1, L
++;for(int i
= 0; i
< limit
; i
++) r
[i
] = (r
[i
>> 1] >> 1) | ((i
& 1) << (L
- 1));}int mul(LL
*ans
,LL
*x
,int ln
,int rn
,LL
*y
,int rm
) {for(int i
=ln
;i
<=rn
;i
++) a
[i
-ln
]=x
[i
]%P
;for(int i
=1;i
<=rm
;i
++) b
[i
]=y
[i
]%P
; int n
=rn
-ln
+1,m
=rm
;init(rn
,rm
);ntt(a
, 1); ntt(b
, 1); ntt(a
, -1); LL inv
= fastpow(limit
, P
- 2);for(int i
= 0; i
<= ln
+ rm
; i
++) ans
[i
]=a
[i
]*inv
%P
;for(int i
=0;i
<limit
;i
++) a
[i
]=0,b
[i
]=0;return rn
+rm
;}}NT
;void solve(int l
,int r
) {if(l
==r
) {if(l
==0) f
[l
]=1;return;} int mid
=(l
+r
)>>1;solve(l
,mid
);int len
=r
-l
+1;for(int i
=l
;i
<=mid
;i
++) a
[i
-l
]=f
[i
];for(int i
=0;i
<=len
;i
++) b
[i
]=g
[i
];NT
.init(len
+1,len
); NT
.ntt(a
, 1); NT
.ntt(b
, 1); for(int i
= 0; i
< NT
.limit
; i
++) a
[i
] = (a
[i
] * b
[i
]) % NT
.P
;NT
.ntt(a
, -1); LL inv
= NT
.fastpow(NT
.limit
, NT
.P
- 2);for(int i
= mid
+1; i
<= r
; i
++) f
[i
]+=a
[i
-l
]*inv
%NT
.P
,f
[i
]%=mod
;for(int i
=0;i
<NT
.limit
;i
++) a
[i
]=0,b
[i
]=0;solve(mid
+1,r
);
}int main()
{
scanf("%d",&n
);for(int i
=1;i
<=n
-1;i
++) scanf("%lld",&g
[i
]);NT
.init_qmi();solve(0,n
-1);for(int i
=0;i
<n
;i
++) printf("%lld ",f
[i
]);return 0;
}
創作挑戰賽新人創作獎勵來咯,堅持創作打卡瓜分現金大獎
總結
以上是生活随笔為你收集整理的P4721 【模板】分治 FFT的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。