LibreOJ 6268 分拆数 发表于 2019.12.07 | 分类于 题解 | 13 欧拉 NB! 首先显然地 ∞∑i=0f(i)xi=∞∏i=111−xi。 然后根据欧拉五边形数定理,有 ∞∏i=1(1−xi)=1+∞∑i=1(−1)ixi(3i−1)2(1+xi)。 然后多项式求逆即可。 代码: 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124#include <cstdio>#include <cstring>#include <algorithm>#define add(a,b) (a + b >= mod ? a + b - mod : a + b)#define dec(a,b) (a < b ? a - b + mod : a - b)using namespace std;const int N = 1 << 18;const int mod = 998244353;const int G = 3;inline int fpow(int a,int b){ int ret = 1; for(;b;b >>= 1) (b & 1) && (ret = (long long)ret * a % mod),a = (long long)a * a % mod; return ret;}struct poly{ int a[N + 5]; inline const int &operator[](const int &x) const { return a[x]; } inline int &operator[](const int &x) { return a[x]; } inline void clear(const int &x = 0) { memset(a + x,0,sizeof (a + x)); }} a;int len,n,lg2[N + 5];int rev[N + 5],fac[N + 5],ifac[N + 5],inv[N + 5];int rt[N + 5],irt[N + 5];inline void init(int len){ for(n = 1;n < len;n <<= 1); for(register int i = 2;i <= n;++i) lg2[i] = lg2[i >> 1] + 1; int w = fpow(G,(mod - 1) / n); rt[n >> 1] = 1; for(register int i = (n >> 1) + 1;i <= n;++i) rt[i] = (long long)rt[i - 1] * w % mod; for(register int i = (n >> 1) - 1;i;--i) rt[i] = rt[i << 1]; fac[0] = 1; for(register int i = 1;i <= n;++i) fac[i] = (long long)fac[i - 1] * i % mod; ifac[n] = fpow(fac[n],mod - 2); for(register int i = n;i;--i) ifac[i - 1] = (long long)ifac[i] * i % mod; for(register int i = 1;i <= n;++i) inv[i] = (long long)ifac[i] * fac[i - 1] % mod;}void ntt(poly &a,int type,int n){ type == -1 && (reverse(a.a + 1,a.a + n),1); int lg = lg2[n] - 1; for(register int i = 0;i < n;++i) rev[i] = (rev[i >> 1] >> 1) | ((i & 1) << lg), i < rev[i] && (swap(a[i],a[rev[i]]),1); for(register int w = 2,m = 1,k = n >> 1;w <= n;w <<= 1,m <<= 1,k >>= 1) for(register int i = 0;i < n;i += w) for(register int j = 0;j < m;++j) { int t = (long long)rt[m | j] * a[i | j | m] % mod; a[i | j | m] = dec(a[i | j],t),a[i | j] = add(a[i | j],t); } if(type == -1) for(register int i = 0;i < n;++i) a[i] = (long long)a[i] * inv[n] % mod;}void mul(poly &a,const poly &b,int n){ static poly x,y; x = a,y = b; x.clear(n >> 1),y.clear(n >> 1); ntt(x,1,n),ntt(y,1,n); for(register int i = 0;i < n;++i) x[i] = (long long)x[i] * y[i] % mod; ntt(x,-1,n); a = x;}poly inverse(const poly &f,int n){ static int s[30]; static poly g,h,q; int lim = 1,top = 0; g.clear(); while(n > 1) { s[++top] = n; n = (n + 1) >> 1; } g[0] = fpow(f[0],mod - 2); for(;top;--top) { n = s[top]; for(;lim < (n << 1);lim <<= 1); q = g,h = f; for(register int i = n;i < lim;++i) h[i] = 0; ntt(g,1,lim),ntt(h,1,lim); for(register int i = 0;i < lim;++i) g[i] = (long long)g[i] * g[i] % mod * h[i] % mod; ntt(g,-1,lim); for(register int i = 0;i < n;++i) g[i] = dec(add(q[i],q[i]),g[i]); for(register int i = n;i < lim;++i) g[i] = 0; } return g;}int main(){ scanf("%d",&len),init((len + 1) << 1),a[0] = 1; for(register int i = 1;i * (3 * i - 1) / 2 <= len;++i) a[i * (3 * i - 1) / 2] = (i & 1) ? mod - 1 : 1, i * (3 * i + 1) / 2 <= len && (a[i * (3 * i + 1) / 2] = (i & 1) ? mod - 1 : 1); a = inverse(a,len + 1); for(register int i = 1;i <= len;++i) printf("%d\n",a[i]);} 本文作者: Alpha1022 本文链接: https://www.alpha1022.me/articles/loj-6268.htm 版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-ND 4.0 许可协议。转载请注明出处!