結果
問題 | No.754 畳み込みの和 |
ユーザー | hashiryo |
提出日時 | 2019-07-08 19:08:06 |
言語 | C++14 (gcc 12.3.0 + boost 1.83.0) |
結果 |
AC
|
実行時間 | 360 ms / 5,000 ms |
コード長 | 4,769 bytes |
コンパイル時間 | 2,181 ms |
コンパイル使用メモリ | 181,808 KB |
実行使用メモリ | 9,728 KB |
最終ジャッジ日時 | 2024-10-09 06:18:37 |
合計ジャッジ時間 | 4,554 ms |
ジャッジサーバーID (参考情報) |
judge3 / judge2 |
(要ログイン)
テストケース
テストケース表示入力 | 結果 | 実行時間 実行使用メモリ |
---|---|---|
testcase_00 | AC | 355 ms
9,604 KB |
testcase_01 | AC | 356 ms
9,604 KB |
testcase_02 | AC | 360 ms
9,728 KB |
ソースコード
#include<bits/stdc++.h> #define debug(x) cerr << #x << ": " << x << endl #define debugArray(x,n) for(long long hoge = 0; (hoge) < (n); ++ (hoge)) cerr << #x << "[" << hoge << "]: " << x[hoge] << endl using namespace std; typedef long long ll; typedef unsigned long long ull; typedef vector<ll> vll; const ll INF = LLONG_MAX/2; const ll MOD = 1e9+7; const double EPS=1e-12; namespace NTT{ ll extgcd(ll a, ll b, ll& x, ll& y) { ll g = a; x = 1; y = 0; if(b != 0) { g = extgcd(b, a % b, y, x); y -= (a / b) * x; } return g; } ll mod_inv(ll a, ll m) { ll x, y; extgcd(a, m, x, y); return (m + x)% m; } ll mod_pow(ll x, ll e,int mod){ ll ret=1; while(e){ if(e&1)ret=ret*x%mod; x=x*x%mod; e>>=1; } return ret; } ll garner(vector<ll> m, vector<ll> u, int mod) { const int n = m.size(); vector<ll> inv_prod(n); { for(int i = 1; i < n; ++i) { ll prod = m[0] % m[i]; for(int j = 1; j < i; ++j) { prod = (prod * m[j]) % m[i]; } inv_prod[i] = mod_inv(prod, m[i]); } } vector<ll> v(n); v[0] = u[0]; for(int i = 1; i < n; ++i) { ll tmp = v[i - 1]; for(int j = i - 2; j >= 0; --j) { tmp = (tmp * m[j] + v[j]) % m[i]; } v[i] = ((u[i] - tmp) * inv_prod[i]) % m[i]; if(v[i] < 0) v[i] += m[i]; } ll res = v[n - 1]; for(int i = n - 2; i >= 0; --i) { res = (res * m[i] + v[i]) % mod; } return res; } template <int Mod, int PrimitiveRoot> class FMT { public: // assertion: v.size() == 2 ^ m static vector<int> fft(vector<int> v, bool inv) { const int n = v.size(); assert((n ^ (n & -n)) == 0); for(int i=0;i<n;i++)v[i]%=Mod; int ww = mod_pow(PrimitiveRoot, (Mod-1) / n, Mod); if(inv) ww = mod_inv(ww, Mod); for(int m = n; m >= 2; m >>= 1) { const int mh = m >> 1; int w = 1; for(int i = 0; i < mh; ++i) { for(int j = i; j < n; j += m) { const int k = j + mh; int x = v[j] - v[k]; if(x < 0) x += Mod; v[j] += - Mod + v[k]; if(v[j] < 0) v[j] += Mod; v[k] = (1LL * w * x) % Mod; } w = (1LL * w * ww) % Mod; } ww = (1LL * ww * ww) % Mod; } int i = 0; for(int j = 1; j < n - 1; ++j) { for(int k = n >> 1; k > (i ^= k); k >>= 1); if(j < i) swap(v[i], v[j]); } if(inv) { const int inv_n = mod_inv(n, Mod); for(auto& x : v) { x = (1LL * x * inv_n) % Mod; assert(0 <= x && x < Mod); } } return v; } static vector<int> multiply(vector<int> f, vector<int> g) { int sz = 1; const int m = f.size() + g.size() - 1; while(sz < m) sz *= 2; f.resize(sz), g.resize(sz); f = fft(move(f), false); g = fft(move(g), false); for(int i = 0; i < sz; ++i) f[i] = (1LL * f[i] * g[i]) % Mod; return fft(move(f), true); } static int get_mod() {return Mod;} }; using FMT_1 = FMT<167772161, 3>; // 5 * 2^25 + 1 using FMT_2 = FMT<469762049, 3>; // 7 * 2^26 + 1 using FMT_3 = FMT<1224736769, 3>; // 73 * 2^24 + 1 vector<int> mod_multiply(vector<int> f, vector<int> g, const int mod ){ for(auto& x : f) x %= mod; for(auto& y : g) y %= mod; const auto v1 = FMT_1::multiply(f, g); const auto v2 = FMT_2::multiply(f, g); const auto v3 = FMT_3::multiply(f, g); vector<int> res(v1.size()); vector<ll> m = {FMT_1::get_mod(), FMT_2::get_mod(), FMT_3::get_mod()}; for(int i = 0; i < (int)v1.size(); ++i) { vector<ll> u = {v1[i], v2[i], v3[i]}; res[i] = garner(m, u, mod); } return res; } } signed main(){ cin.tie(0); ios::sync_with_stdio(false); ll N;cin>>N; vector<int> a(N+1),b(N+1); for(ll i=0;i<=N;i++){ cin>>a[i]; } for(ll i=0;i<=N;i++){ cin>>b[i]; } auto c=NTT::mod_multiply(a,b,MOD); ll ans=0; for(ll i=0;i<=N;i++){ ans = (ans+c[i])%MOD; } cout<<ans<<endl; return 0; }