結果
問題 | No.754 畳み込みの和 |
ユーザー | ate |
提出日時 | 2020-09-14 23:51:26 |
言語 | C++17 (gcc 12.3.0 + boost 1.83.0) |
結果 |
AC
|
実行時間 | 340 ms / 5,000 ms |
コード長 | 6,876 bytes |
コンパイル時間 | 1,622 ms |
コンパイル使用メモリ | 99,892 KB |
実行使用メモリ | 15,108 KB |
最終ジャッジ日時 | 2024-06-22 01:01:58 |
合計ジャッジ時間 | 3,575 ms |
ジャッジサーバーID (参考情報) |
judge1 / judge3 |
(要ログイン)
テストケース
テストケース表示入力 | 結果 | 実行時間 実行使用メモリ |
---|---|---|
testcase_00 | AC | 340 ms
14,984 KB |
testcase_01 | AC | 335 ms
15,108 KB |
testcase_02 | AC | 338 ms
15,108 KB |
ソースコード
#include<iostream> #include<vector> #include<cassert> #include<tuple> constexpr int primitive_root(int m){ if(m==2)return 1; if(m==167772161)return 3; if(m==469762049)return 3; if(m==754974721)return 11; if(m==998244353)return 3; return 0; } template<int64_t p> struct F_p{ using value_type = int64_t; static constexpr inline value_type get_mod(){return p;} value_type value; constexpr F_p():value(value_type{}){} template<class T>constexpr F_p(T v):value(static_cast<value_type>(v<0?v%p+p:v%p)){} // operator +, -, *, /, ^ constexpr F_p operator + (const F_p& other)const{ return F_p(*this) += other; } constexpr F_p operator - (const F_p& other)const{ return F_p(*this) -= other; } constexpr F_p operator * (const F_p& other)const{ return F_p(*this) *= other; } constexpr F_p operator / (const F_p& other)const{ return F_p(*this) /= other; } template<class T> constexpr F_p operator ^ (const T other)const{ return F_p(*this) ^= other; } constexpr F_p &operator += (const F_p& other){ value+=other.value; if(value>p)value-=p; return *this; } constexpr F_p &operator -= (const F_p& other){ value-=other.value; if(value<0)value+=p; return *this; } constexpr F_p &operator *= (const F_p& other){ value*=other.value; if(value>p)value%=p; return *this; } constexpr F_p &operator /= (const F_p& other){ value*=other.inverse(); if(value>p)value%=p; return *this; } template<class T> constexpr F_p &operator ^= (const T n){ value = mpow(n).value; return *this; } // ext_gcd,inverse,mpow static constexpr value_type ext_gcd(value_type a,value_type b,value_type& x,value_type& y){ if(b==0){x=1,y=0;return a;} value_type d=ext_gcd(b,a%b,y,x); y-=a/b*x;return d; } constexpr value_type inverse()const{ value_type x,y; ext_gcd(value,p,x,y); return x<0?x%p+p:x%p; } template<class T> static constexpr value_type inverse(T val){ value_type x,y; ext_gcd(val,p,x,y); return x<0?x%p+p:x%p; } template<class T> constexpr F_p mpow(T n)const{ F_p res(1),vn(*this); while(n){ if(n&1)res*=vn; vn*=vn; n>>=1; } return res; } template<class T,class U> static constexpr T mpow(T a,U b){ F_p x(a); return static_cast<T>(x.mpow(b).value); } // operator iostream constexpr friend std::istream &operator >> (std::istream& is,F_p& fp){ is>>fp.value; return is; }constexpr friend std::ostream &operator << (std::ostream& os,const F_p& fp){ os<<fp.value; return os; } }; template<int64_t MOD,int primitive_root> struct number_theoretic_transform{ using value_type = F_p<MOD>; using vector_t = std::vector<value_type>; template<class T> static constexpr value_type pow(value_type v,T t){return v^t;} static constexpr int64_t get_mod(){return MOD;} number_theoretic_transform() = default; static void ntt(vector_t& a,bool inv=false){ const int n = std::size(a); for(int i=0,j=1;j+1<n;++j){ for(int k=n>>1;k>(i^=k);k>>=1); if(i<j)std::swap(a[i],a[j]); } for(int t=2;t<=n;t<<=1){ value_type bw = pow(primitive_root,(MOD-1)/t); if(inv)bw = bw.inverse(); for(int i=0;i<n;i+=t){ value_type w = 1; for(int j=0;j<t/2;++j){ const value_type x = a[i+j]; const value_type y = a[i+j+t/2]*w; a[i+j] = x+y; a[i+j+t/2] = x-y; w *= bw; } } } if(inv)for(auto& ai:a)ai/=n; } template<class T> static vector_t convolution(std::vector<T> const& a,std::vector<T> const& b){ const int sz_a = std::size(a); const int sz_b = std::size(b); const int m = sz_a+sz_b-1; int n = 1; while(n<m)n<<=1; vector_t ntt_a(n),ntt_b(n),ntt_c(n); for(int i=0;i<sz_a;++i)ntt_a[i]=static_cast<value_type>(a[i]); for(int i=0;i<sz_b;++i)ntt_b[i]=static_cast<value_type>(b[i]); ntt(ntt_a); ntt(ntt_b); for(int i=0;i<n;++i)ntt_c[i]=ntt_a[i]*ntt_b[i]; bool inverse = true; ntt(ntt_c,inverse); ntt_c.resize(m); return ntt_c; } }; using NTT_998244353 = number_theoretic_transform<998244353,primitive_root(998244353)>; struct NTT{ using NTT_1 = number_theoretic_transform<998244353,3>; using NTT_2 = number_theoretic_transform<754974721,11>; using NTT_3 = number_theoretic_transform<469762049,3>; NTT(){} static std::tuple<int64_t,int64_t,int64_t> ext_gcd(int64_t a,int64_t b){ if(b==0)return {a,1,0}; auto[d,y,x]=ext_gcd(b,a%b); y-=a/b*x;return {d,x,y}; } static constexpr inline int64_t mod(int64_t a,int64_t m){ a%=m;return(a<0?a+m:a); } static int64_t mod_inv(int64_t a,int64_t m){ auto[d,x,y]=ext_gcd(a,m);return(d!=1?-1:mod(x,m)); } static int64_t gerner (std::vector<int64_t> b,std::vector<int64_t> m,int64_t const MOD){ using i64 = int64_t; assert(0<std::size(b)); assert(std::size(b)==std::size(m)); int n = std::size(b); // gerner m.emplace_back(MOD); std::vector<i64> coeffs(std::size(m),1); std::vector<i64> constants(std::size(m),0); for(int k=0;k<n;++k){ i64 m_inv = mod_inv(coeffs[k],m[k]); i64 t = mod((b[k]-constants[k])*m_inv,m[k]); for(int i=k+1;i<std::size(m);++i){ (constants[i] += t*coeffs[i]) %= m[i]; (coeffs[i] *= m[k]) %= m[i]; } } return constants.back(); } template<class T> static std::vector<int64_t> convolution(std::vector<T>const& a,std::vector<T>const& b,const int64_t MOD){ auto ntt1 = NTT_1::convolution(a,b); auto ntt2 = NTT_2::convolution(a,b); auto ntt3 = NTT_3::convolution(a,b); const int n = std::size(a)+std::size(b)-1; const int m = 3; std::vector<int64_t> conv(n),mods = {NTT_1::get_mod(),NTT_2::get_mod(),NTT_3::get_mod()}; for(int i=0;i<n;++i){ std::vector<int64_t> b = {static_cast<int64_t>(ntt1[i].value), static_cast<int64_t>(ntt2[i].value), static_cast<int64_t>(ntt3[i].value)}; conv[i] = gerner(b,mods,MOD); } return conv; } }; int main(){ using namespace std; std::cin.tie(nullptr); std::ios_base::sync_with_stdio(false); constexpr char newl = '\n'; int n; cin>>n; vector<int64_t> a(n+1),b(n+1); for(auto& ai:a)cin>>ai; for(auto& bi:b)cin>>bi; auto c = NTT::convolution(a,b,1e9+7); //for(auto ci:c)cout<<ci<<" ";cout<<newl; F_p<(int)1e9+7> ans = 0; for(int i=0;i<=n and i<size(c);++i)ans+=c[i]; cout<<(ans)<<endl; } void solve_fft(){ using namespace std; std::cin.tie(nullptr); std::ios_base::sync_with_stdio(false); constexpr char newl = '\n'; int n; cin>>n; vector<int64_t> a(n),b(n); for(int i=0;i<n;++i)cin>>a[i]>>b[i]; auto c = NTT_998244353::convolution(a,b); cout<<0<<newl; for(auto ci:c)cout<<ci<<newl; }