Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- //misaka will carry me to master
- #include <iostream>
- #include <cstdio>
- #include <cstring>
- #include <cmath>
- #include <utility>
- #include <cassert>
- #include <algorithm>
- #include <vector>
- #include <functional>
- #include <numeric>
- #include <set>
- #include <map>
- #include <complex>
- #define ll long long
- #define lb long double
- #define sz(vec) ((int)(vec.size()))
- #define all(x) x.begin(), x.end()
- #define pb push_back
- #define mp make_pair
- const lb eps = 1e-9;
- const ll mod = 1e9 + 7, ll_max = 1e18;
- //const ll mod = (1 << (23)) * 119 +1;
- const int MX = 2e5 +10, int_max = 0x3f3f3f3f;
- using namespace std;
- #define lp std::complex<double>
- #define hsb(x) (31 - __builtin_clz(x))
- const int D = 19;
- const int NN = (1 << D);
- const lb tau = 4.0 * acos(0);
- //this function returns the reversed version of x with b bits
- int rev(unsigned int x, int b){ //lots of trust
- x = (((x & 0xaaaaaaaa) >> 1) | ((x & 0x55555555) << 1));
- x = (((x & 0xcccccccc) >> 2) | ((x & 0x33333333) << 2));
- x = (((x & 0xf0f0f0f0) >> 4) | ((x & 0x0f0f0f0f) << 4));
- x = (((x & 0xff00ff00) >> 8) | ((x & 0x00ff00ff) << 8));
- //https://aticleworld.com/5-way-to-reverse-bits-of-an-integer/ method 4
- return((x >> 16) | (x << 16)) >> (32 - b);
- }
- //evaluates the roots of unity of poly
- //if op == 1, reverses it as well
- vector<lp> halfft(vector<lp> poly, int op = 0){
- vector<lp> ans(sz(poly)); //answers will be stored here
- static lp tmp[NN]; //auxilary memory
- if(sz(poly) == 1){ //hardcode when its just a constant term
- ans[0] = poly[0];
- return ans;
- }
- int p2 = hsb(sz(poly)); //this denotes log2(sz(poly))
- for(int i = 0; i<sz(poly); i++){
- ans[rev(i, p2)] = poly[i]; //this is the base case of storing it into the bitwise reversal
- }
- for(int k = 1, n = 2; k<=p2; k++, n *= 2){ //find the answer for blocks size 2^k as k goes from 1 -> log2(sz(poly))
- for(int pos = 0; pos < sz(poly); pos += n){ //iterate over the starting spot
- for(int i = 0; i<n; i++){
- lp x_0;
- if(op == 0) x_0 = exp(lp(0, tau*(lb)i/(lb)(n))); // normal root
- else x_0 = exp(lp(0, tau*(lb)(n-i)/(lb)(n))); //inverted root
- tmp[pos + i] = ans[pos + i%(n/2)] + x_0 * ans[pos + n/2 + (i%(n/2))];
- //i am just really smart so this works, i write into ans[] smartly so that i dont overlap
- }
- for(int i = 0; i<n; i++){
- ans[pos + i] = tmp[pos + i]; //copy tmp into ans
- }
- }
- }
- return ans;
- }
- vector<lp> fft(const vector<int>& a, const vector<int>& b){
- int s;
- for(s = 1; s<(sz(a) +sz(b)); s*=2);
- vector<lp> A(s), B(s);
- for(int i = 0; i<s; i++){
- A[i] = B[i] = 0;
- if(i < sz(a)) A[i] = a[i];
- if(i < sz(b)) B[i] = b[i];
- } //make the two size 2^k polynomials A and B
- vector<lp> aa = halfft(A), bb = halfft(B); //halfft A and B
- for(int i = 0; i<sz(aa); i++){
- aa[i] *= bb[i]; //multiply them together
- }
- vector<lp> res = halfft(aa, 1), ans(s);
- for(int i = 0; i<s; i++){
- ans[i] = (lb)(real(res[i]))/(lb)(s); //divide by s and write into the answer
- }
- return ans;
- }
- void solve(){
- int n, m;
- cin >> n >> m;
- n++, m++;
- vector<int> p1(n), p2(m);
- for(int i = 0; i<n; i++){
- cin >> p1[i];
- }
- for(int i =0; i<m; i++){
- cin >> p2[i];
- }
- vector<lp> ans = fft(p1, p2);
- for(int i = 0; i<n + m -1; i++){
- cout << (int)round(real(ans[i])) << " ";
- }
- cout << "\n";
- }
- int main(){
- cin.tie(0) -> sync_with_stdio(0);
- int T = 1;
- //cin >> T;
- while(T--){
- solve();
- }
- return 0;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement