結果
問題 | No.931 Multiplicative Convolution |
ユーザー |
![]() |
提出日時 | 2019-11-22 22:03:51 |
言語 | C++14 (gcc 13.3.0 + boost 1.87.0) |
結果 |
AC
|
実行時間 | 163 ms / 2,000 ms |
コード長 | 3,712 bytes |
コンパイル時間 | 1,401 ms |
コンパイル使用メモリ | 119,916 KB |
実行使用メモリ | 22,012 KB |
最終ジャッジ日時 | 2024-10-11 03:41:50 |
合計ジャッジ時間 | 3,427 ms |
ジャッジサーバーID (参考情報) |
judge3 / judge5 |
(要ログイン)
ファイルパターン | 結果 |
---|---|
sample | AC * 3 |
other | AC * 14 |
ソースコード
#include <cstdio>#include <cstring>#include <iostream>#include <string>#include <cmath>#include <bitset>#include <vector>#include <map>#include <set>#include <queue>#include <deque>#include <algorithm>#include <complex>#include <unordered_map>#include <unordered_set>#include <random>#include <cassert>#include <fstream>#include <utility>#include <functional>#include <time.h>#include <stack>#include <array>#define popcount __builtin_popcountusing namespace std;typedef long long int ll;typedef pair<int, int> P;template< int mod, int primitiveroot >struct NumberTheoreticTransform {vector< vector< int > > rts, rrts;void ensure_base(int N) {if(rts.size() >= N) return;rts.resize(N), rrts.resize(N);for(int i = 1; i < N; i <<= 1) {if(rts[i].size()) continue;int w = mod_pow(primitiveroot, (mod - 1) / (i * 2));int rw = inverse(w);rts[i].resize(i), rrts[i].resize(i);rts[i][0] = 1, rrts[i][0] = 1;for(int k = 1; k < i; k++) {rts[i][k] = mul(rts[i][k - 1], w);rrts[i][k] = mul(rrts[i][k - 1], rw);}}}inline int mod_pow(int x, int n) {int ret = 1;while(n > 0) {if(n & 1) ret = mul(ret, x);x = mul(x, x);n >>= 1;}return ret;}inline int inverse(int x) {return mod_pow(x, mod - 2);}inline int add(int x, int y) {x += y;if(x >= mod) x -= mod;return x;}inline int mul(int a, int b) {return int(1LL * a * b % mod);}void DiscreteFourierTransform(vector< int > &F, bool rev) {const int N = (int) F.size();ensure_base(N);for(int i = 0, j = 1; j + 1 < N; j++) {for(int k = N >> 1; k > (i ^= k); k >>= 1);if(i > j) swap(F[i], F[j]);}for(int i = 1; i < N; i <<= 1) {for(int j = 0; j < N; j += i * 2) {for(int k = 0; k < i; k++) {int s = F[j + k], t = mul(F[j + k + i], rev ? rrts[i][k] : rts[i][k]);F[j + k] = add(s, t), F[j + k + i] = add(s, mod - t);}}}if(rev) {int temp = inverse(N);for(int i = 0; i < N; i++) F[i] = mul(F[i], temp);}}vector< int > Multiply(const vector< int > &A, const vector< int > &B) {int sz = 1;while(sz < A.size() + B.size() - 1) sz <<= 1;vector< int > F(sz), G(sz);for(int i = 0; i < A.size(); i++) F[i] = A[i];for(int i = 0; i < B.size(); i++) G[i] = B[i];DiscreteFourierTransform(F, false);DiscreteFourierTransform(G, false);for(int i = 0; i < sz; i++) F[i] = mul(F[i], G[i]);DiscreteFourierTransform(F, true);F.resize(A.size() + B.size() - 1);return F;}};const ll MOD=998244353;ll powmod(ll a, ll k, ll mod){ll ap=a, ans=1;while(k){if(k&1){ans*=ap;ans%=mod;}ap=ap*ap;ap%=mod;k>>=1;}return ans;}int p, r;int l[100010];int q[100010];void root(){r=1;for(; ; r++){ll pp=1;bool dame=0;for(int i=0; i<p-2; i++){pp*=r;pp%=p;if(pp==1){dame=1;break;}}if(!dame){break;}}ll pp=1;for(int i=0; i<p-1; i++){l[pp]=i;q[i]=pp;pp*=r;pp%=p;}}int main(){cin>>p;root();int a[100010], b[100010];vector<int> a1(p-1), b1(p-1);for(int i=1; i<p; i++){cin>>a[i];}for(int i=1; i<p; i++){cin>>b[i];}for(int i=0; i<p-1; i++){a1[i]=a[q[i]];b1[i]=b[q[i]];}NumberTheoreticTransform<MOD, 3> ntt;vector<int> c1=ntt.Multiply(a1, b1);int c[100010]={};for(int i=0; i<=2*(p-2); i++){c[q[i%(p-1)]]+=c1[i];c[q[i%(p-1)]]%=MOD;}for(int i=1; i<p; i++){cout<<c[i]<<" ";}cout<<endl;return 0;}