Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include<bits/stdc++.h>
- using namespace std;
- using cd = complex<double>;
- const double PI = acos(-1);
- /**
- when invert is true this function will act as inverse dft otherwise dft
- when invert is false
- it take an array of co-efficient and return as output array
- when invert is true
- it take an array of output and return array of co-efficient
- */
- void fft(vector<cd> & a, bool invert) {
- int n = a.size();
- for (int i = 1, j = 0; i < n; i++) {
- int bit = n >> 1;
- for (; j & bit; bit >>= 1)
- j ^= bit;
- j ^= bit;
- if (i < j)
- swap(a[i], a[j]);
- }
- for (int len = 2; len <= n; len <<= 1) {
- double ang = 2 * PI / len * (invert ? -1 : 1);
- cd wlen(cos(ang), sin(ang));
- for (int i = 0; i < n; i += len) {
- cd w(1);
- for (int j = 0; j < len / 2; j++) {
- cd u = a[i+j], v = a[i+j+len/2] * w;
- a[i+j] = u + v;
- a[i+j+len/2] = u - v;
- w *= wlen;
- }
- }
- }
- if (invert) {
- for (cd & x : a)
- x /= n;
- }
- }
- /**
- this function take to array of coefficient of two polynomial
- and return an array of coefficient of a polynomial which is multiplication of previous polynomials
- */
- vector<int> multiply(vector<int> const& a, vector<int> const& b) {
- vector<cd> fa(a.begin(), a.end()), fb(b.begin(), b.end());
- int n = 1;
- while (n < a.size() + b.size())
- n <<= 1;
- fa.resize(n);
- fb.resize(n);
- fft(fa, false);
- fft(fb, false);
- for (int i = 0; i < n; i++)
- fa[i] *= fb[i];
- fft(fa, true);
- vector<int> result(n);
- for (int i = 0; i < n; i++)
- result[i] = round(fa[i].real());
- return result;
- }
- /**
- ntt
- calculate those constant first
- calculation:
- mod=c*2^k+1
- find any c and k;
- find g = primitive root of mod
- find root=g^c
- find root_1=modular multiplicative inverse root=(1/root)%mod
- find root_pw=2^k
- */
- const int mod = 7340033;
- const int root = 5;
- const int root_1 = 4404020;
- const int root_pw = 1 << 20;
- void fft(vector<int> & a, bool invert) {
- int n = a.size();
- for (int i = 1, j = 0; i < n; i++) {
- int bit = n >> 1;
- for (; j & bit; bit >>= 1)
- j ^= bit;
- j ^= bit;
- if (i < j)
- swap(a[i], a[j]);
- }
- for (int len = 2; len <= n; len <<= 1) {
- int wlen = invert ? root_1 : root;
- for (int i = len; i < root_pw; i <<= 1)
- wlen = (int)(1LL * wlen * wlen % mod);
- for (int i = 0; i < n; i += len) {
- int w = 1;
- for (int j = 0; j < len / 2; j++) {
- int u = a[i+j], v = (int)(1LL * a[i+j+len/2] * w % mod);
- a[i+j] = u + v < mod ? u + v : u + v - mod;
- a[i+j+len/2] = u - v >= 0 ? u - v : u - v + mod;
- w = (int)(1LL * w * wlen % mod);
- }
- }
- }
- if (invert) {
- int n_1 = inverse(n, mod);
- for (int & x : a)
- x = (int)(1LL * x * n_1 % mod);
- }
- }
- /**
- primitive root generator
- */
- int generator (int p) {
- vector<int> fact;
- int phi = p-1, n = phi;
- for (int i=2; i*i<=n; ++i)
- if (n % i == 0) {
- fact.push_back (i);
- while (n % i == 0)
- n /= i;
- }
- if (n > 1)
- fact.push_back (n);
- for (int res=2; res<=p; ++res) {
- bool ok = true;
- for (size_t i=0; i<fact.size() && ok; ++i)
- ok &= powmod (res, phi / fact[i], p) != 1;
- if (ok) return res;
- }
- return -1;
- }
- int main()
- {
- cout<<generator(7340033)<<endl;
- return 0;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement