求卡常/证明是假做法
查看原帖
求卡常/证明是假做法
219595
Vocalise楼主2020/7/16 09:36

倍增FFT,卡在#17的点,开o2也没用。

大概是不会假的,肯定是不会假的。

代码如下。

#include <cstdio>
#include <iostream>
#include <cstring>
#include <cmath>
#include <algorithm>

typedef long long ll;
const int p = 998244353;
const int MAXN = 270000;

inline int read() {
    int x = 0,f = 1; char ch = getchar();
    while(ch > '9' || ch < '0') { if(ch == '-') f = -1; ch = getchar(); }
    do x = (x * 10 + ch - 48) % p, ch = getchar(); while(ch >= '0' && ch <= '9');
    return (x * f % p + p) % p;
}

inline void print(int x) {
	if(x > 9) print(x / 10);
	std::putchar(x % 10 + 48);
}

int n,k,r[MAXN],inv[MAXN],gn[MAXN];
int f[3][MAXN],g[5][MAXN];

inline int fastpow(int a,int b) {
    int res = 1; a %= p;
    while(b) {
        if(b & 1) res = (ll)res * a % p;
        a = (ll)a * a % p;
        b >>= 1;
    }
    return res;
}

inline void NTT(int *a,int N) {
    for(register int i = 0;i < N;i++) if(i < r[i]) std::swap(a[i],a[r[i]]);
    for(register int n = 2,m = 1;n <= N;m = n, n <<= 1) {
        for(register int l = 0;l < N;l += n) {
            int g = 1,t1,t2;
            for(register int i = l;i < l + m;i++) {
                t1 = a[i], t2 = (ll)g * a[i + m] % p;
                a[i] = ((ll)t1 + t2) % p;
                a[i + m] = ((ll)t1 - t2 + p) % p;
                g = (ll)g * gn[n] % p;
            }
        }
    }
    return;
}

inline void INTT(int *a,int N) {
    NTT(a,N);
    for(int i = 1;i <= N >> 1;i++) std::swap(a[i],a[N - i]);
    for(register int i = 0;i < N;i++) a[i] = (ll)a[i] * inv[N] % p;
}

inline void Double(int n,int N)  {
    NTT(f[0],N); NTT(f[1],N); NTT(f[2],N);
	for(register int i = 0;i < N;i++) {
    	g[0][i] = (ll)f[0][i] * f[0][i] % p, g[1][i] = (ll)f[1][i] * f[1][i] % p;
    	g[2][i] = (ll)f[2][i] * f[2][i] % p, g[3][i] = (ll)f[0][i] * f[1][i] % p;
    	g[4][i] = (ll)f[1][i] * f[2][i] % p;
	}
	INTT(g[0],N); INTT(g[1],N); INTT(g[2],N); INTT(g[3],N); INTT(g[4],N);
	for(register int i = 0;i < N;i++) {
		f[0][i] = ((ll)g[0][i] + (i ? g[1][i - 1] : 0)) % p;
		f[1][i] = ((ll)g[3][i] + (i ? g[4][i - 1] : 0)) % p;
		f[2][i] = ((ll)g[1][i] + (i ? g[2][i - 1] : 0)) % p;
	}
    for(register int i = 0;i < N;i++) g[0][i]= g[1][i] = g[2][i] = g[3][i] = g[4][i] = 0;
	for(register int i = n;i < N;i++) f[0][i] = f[1][i] = f[2][i] = 0;
	return;
}

inline void Add(int n) {
	for(register int i = 0;i < n;i++) f[2][i] = f[1][i], f[1][i] = f[0][i];
	f[0][0] = 1;
	for(register int i = 1;i < n;i++) f[0][i] = (((ll)f[1][i - 1] + f[2][i - 1]) % p + f[1][i]) % p;
}

int main() {
	inv[1] = 1;
	for(int i = 2;i < MAXN;i++) inv[i] = (ll)inv[p % i] * (p - p / i) % p;
	n = read(), k = read(); int h = log2(n);
	f[0][0] = f[1][0] = f[0][1] = 1;
    int N = 1, l = -1; while(N <= (k + 5) << 1) N <<= 1, l++, gn[N] = fastpow(3,(p - 1) / N);
    for(register int i = 1;i < N;i++) r[i] = (r[i >> 1] >> 1) | ((i & 1) << l);
	for(register int i = h - 1;i >= 0;i--) {
		Double(k + 5,N);
		if(n & (1 << i)) Add(k + 5);
	}
	for(register int i = 1;i <= k;i++) print(f[0][i]), std::putchar(' ');
	std::putchar('\n');
    return 0;
}
2020/7/16 09:36
加载中...