結果
問題 | No.931 Multiplicative Convolution |
ユーザー | ace_amuro |
提出日時 | 2021-01-20 16:33:47 |
言語 | C++14 (gcc 12.3.0 + boost 1.83.0) |
結果 |
AC
|
実行時間 | 124 ms / 2,000 ms |
コード長 | 3,181 bytes |
コンパイル時間 | 794 ms |
コンパイル使用メモリ | 73,792 KB |
実行使用メモリ | 17,792 KB |
最終ジャッジ日時 | 2024-12-23 06:14:09 |
合計ジャッジ時間 | 3,009 ms |
ジャッジサーバーID (参考情報) |
judge1 / judge5 |
(要ログイン)
テストケース
テストケース表示入力 | 結果 | 実行時間 実行使用メモリ |
---|---|---|
testcase_00 | AC | 2 ms
5,248 KB |
testcase_01 | AC | 2 ms
5,248 KB |
testcase_02 | AC | 2 ms
5,248 KB |
testcase_03 | AC | 2 ms
5,248 KB |
testcase_04 | AC | 2 ms
5,248 KB |
testcase_05 | AC | 2 ms
5,248 KB |
testcase_06 | AC | 3 ms
5,248 KB |
testcase_07 | AC | 15 ms
5,376 KB |
testcase_08 | AC | 123 ms
17,792 KB |
testcase_09 | AC | 111 ms
17,536 KB |
testcase_10 | AC | 121 ms
17,664 KB |
testcase_11 | AC | 111 ms
17,408 KB |
testcase_12 | AC | 110 ms
16,384 KB |
testcase_13 | AC | 122 ms
17,536 KB |
testcase_14 | AC | 123 ms
17,792 KB |
testcase_15 | AC | 124 ms
17,792 KB |
testcase_16 | AC | 123 ms
17,664 KB |
ソースコード
#include<cstdio> #include<cstring> #include<iostream> #include<cmath> #include<algorithm> using namespace std; typedef long long LL; LL ww[101]; LL* e = ww + 50; const int MAXN = (1<<21)+5; const int MAXQ = 1e5; const LL P = 998244353; LL qpow(LL a, LL k, LL p) { LL c = 1; while (k) { if (k & 1) c = (c * a) % p; k >>= 1; a = (a * a) % p; } return c; } void primeroot(LL* e, const LL& P, const LL& g) { int s = 0; LL q = P - 1; while ((q & 1) == 0) {s++; q >>= 1;} LL w = qpow(g, q, P); LL invw = qpow(w, P - 2, P); for (int h = s; h >= 0; h--) { e[h] = w; e[-h] = invw; w = (w * w) % P; invw = (invw * invw) % P; } } void ntt(LL* f, const int& h, const int& type) { if (h == 0) return; LL f0[1 << (h - 1)], f1[1 << (h - 1)]; int n = 1 << h; for (int i = 0; i < n; i+=2) f0[i/2] = f[i]; ntt(f0, h - 1, type); for (int i = 1; i < n; i+=2) f1[i/2] = f[i]; ntt(f1, h - 1, type); LL w = e[type * h]; LL x = 1; for (int k = 0; k < n / 2; k++) { f[k] = f0[k] + x * f1[k]; f[k] %= P; f[k + n / 2] = f0[k] - x * f1[k]; f[k + n / 2] %= P; x *= w; x %= P; } } LL work(LL P){ LL x=P-1; LL p[1000],cnt=0; for(LL i=2;i*i<=x;i++){ if(x%i==0){ while(x%i==0){ x/=i; } p[cnt]=i; cnt++; } } if(x>1){ p[cnt]=x; cnt++; } for(LL g=2;g<=P-1;g++){ bool flag=1; for(int i=0;i<cnt;i++){ if(qpow(g,(P-1)/p[i],P)==1){ flag=false; break; } } if(flag){ return g; } } return 1; } LL q,g; LL A[MAXQ],B[MAXQ],C[MAXQ],logp[MAXQ],gpow[MAXQ]; LL a[MAXN],b[MAXN],c[MAXN]; int main() { scanf("%lld",&q); for(int i=1;i<q;i++) scanf("%lld",A+i); for(int i=1;i<q;i++) scanf("%lld",B+i); if(q==2){printf("%lld\n",A[1]*B[1]%P);return 0;} g=work(q); gpow[0]=1; logp[1]=0; a[0]=A[1];b[0]=B[1]; for(int i=1;i<q-1;i++){ gpow[i]=g*gpow[i-1]%q; logp[gpow[i]]=i; a[i]=A[gpow[i]]; b[i]=B[gpow[i]]; } //printf("log:");for (int i = 0; i < q; i++)printf(" %lld",logp[i]);printf("\n"); primeroot(e, P, 3); int deg = 1, h = 0; while (deg < 2 * q) {deg <<= 1; h++;} //printf("a:");for (int i = 0; i < deg; i++)printf(" %lld",a[i]);printf("\n"); //printf("b:");for (int i = 0; i < deg; i++)printf(" %lld",b[i]);printf("\n"); ntt(a, h, 1); ntt(b, h, 1); for (int i = 0; i < deg; i++) c[i] = a[i] * b[i] % P; ntt(c, h, -1); LL inv = qpow(deg, P - 2, P); for (int i = 0; i < deg; i++) { c[i] = (c[i] * inv) % P; c[i] = (c[i] + P) % P; } //printf("c:");for (int i = 0; i < deg; i++)printf(" %lld",c[i]);printf("\n"); for (int i = 0; i < deg; i++){ C[i%(q-1)]+=c[i]; C[i%(q-1)]%=P; } //printf("C:");for (int i = 0; i < q; i++)printf(" %lld",C[i]);printf("\n"); for(int f=1;f<=q-1;f++){ printf("%lld ",C[logp[f]]); } return 0; }