1. 程式人生 > 其它 >luogu P5667 拉格朗日插值2

luogu P5667 拉格朗日插值2

https://www.luogu.com.cn/problem/P5667

主要是要知道可以把它先便偏移一下,然後再卷積

\(b[i]=\frac{1}{m-n+i}\)

code:

#include<bits/stdc++.h>
#define ll long long
#define mod 998244353
#define N 1600050
using namespace std;
int add(int x, int y) { x += y;
    if(x >= mod) x -= mod;
    return x;
}
int sub(int x, int y) { x -= y;
    if(x < 0) x += mod;
    return x;
}
int mul(int x, int y) {
    return 1ll * x * y % mod;
}
ll qpow(ll x, ll y) {
    ll ret = 1;
    for(; y; y >>= 1, x = x * x % mod) if(y &  1) ret = ret * x % mod;
    return ret;
}
ll inv(int x) {
    return qpow(x, mod - 2);
}
ll fac[N], ifac[N], mfac[N];
void init(int n, int m) {
    fac[0] = 1;
    for(int i = 1; i <= n; i ++) fac[i] = fac[i - 1] * i % mod;
    ifac[n] = inv(fac[n]);
    for(int i = n - 1; i >= 0; i --) ifac[i] = ifac[i + 1] * (i + 1) % mod;

    mfac[0] = 1;
    for(int i = m - n; i <= m; i ++) mfac[0] = mfac[0] * i % mod;
    for(int i = 1; i <= n; i ++) {
        mfac[i] = mfac[i - 1] * (m + i) % mod * inv(m + i - n - 1) % mod;
    }
  //  for(int i = 0; i <= n; i ++) printf("%lld ", mfac[i]); printf("\n");
}

const int G = 3;
const int Ginv = inv(G);
int rev[N];
void ntt(int *a, int n, int o) {
	
    for(int i = 1; i < n; i ++) if(rev[i] > i) swap(a[rev[i]], a[i]);
	
    for(int len = 2; len <= n; len <<= 1) {
		int w0 = qpow((o == 1)? G : Ginv, (mod - 1) / len);
		for(int j = 0; j < n; j += len) {
			int wn = 1;
			for(int k = j; k < j + (len >> 1); k ++, wn = mul(wn, w0)) {
				int X = a[k], Y = mul(a[k + (len >> 1)], wn);
				a[k] = add(X, Y), a[k + (len >> 1)] = sub(X, Y);
			}
		}
	}
	int ninv = qpow(n, mod - 2);
	if(o == -1)
		for(int i = 0; i < n; i ++) a[i] = mul(a[i], ninv);
}
int n, m, f[N], a[N], b[N];
int main() {
    scanf("%d%d", &n, &m);
    for(int i = 0; i <= n; i ++) scanf("%d", &f[i]);
    init(n, m);

    for(int i = 0; i <= n; i ++) a[i] = 1ll * f[i] * qpow(mod - 1, n - i) % mod * ifac[i] % mod * ifac[n -i] % mod;
    for(int i = 0; i <= n + n; i ++) b[i] = inv(m - n + i);

    // for(int i = 0; i <= n; i ++) printf("%d ", a[i]); printf("\n");
    // for(int i = 0; i <= n + n; i ++) printf("%d ", b[i]); printf("\n");
    int len = 1;
    for(; len <= n + n + n; len <<= 1);
    for(int i = 1; i <= len; i ++) rev[i] = (rev[i >> 1] >> 1) | ((i & 1) * (len >> 1));
    ntt(a, len, 1), ntt(b, len, 1);
     for(int i = 0; i < len; i ++) a[i] = mul(a[i], b[i]);
     ntt(a, len, -1);
 //   for(int i = 0; i <= n + n; i ++) printf("%d ", a[i]); printf("\n");
    for(int i = n; i <= n + n; i ++) printf("%d ", mul(mfac[i - n], a[i]));
    return 0;
}