update:哈哈,刚刚拿到一份fft算整数取膜的模板,赶紧来试一下,,简直爽歪歪,大概以后就告别crt合并ntt了(第二份代码)
#include<iostream>
#include<cstdio>
#include<math.h>
#include<algorithm>
#include<map>
#include<set>
#include<bitset>
#include<stack>
#include<queue>
#include<string.h>
#include<cstring>
#include<vector>
#include<time.h>
#include<stdlib.h>
using namespace std;
#define INF 0x3f3f3f3f
#define INFLL 0x3f3f3f3f3f3f3f3f
#define FIN freopen("input.txt","r",stdin)
#define mem(x,y) memset(x,y,sizeof(x))
typedef unsigned long long ULL;
typedef long long LL;
#define fuck(x) cout<<"x"<<endl;
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
typedef pair<pair<int,int>,int> PIII;
typedef pair<LL,LL> PII;
const double eps=1e-100;
const int MX=444444;
const int P=998244353;
int n;
LL F[MX],invF[MX];
LL quick_power(LL a, LL x, LL mod)
{
LL ans = 1;
a %= mod;
while(x)
{
if(x & 1)ans = ans * a % mod;
x >>= 1;
a = a * a % mod;
}
return ans;
}
void init()
{
F[0] = 1;
for(int i = 1; i < MX; i++) F[i] = ((LL)F[i - 1] * i) % P;
invF[MX - 1] = quick_power(F[MX - 1],P - 2,P);
for(int i = MX - 2; i >= 0; i--) invF[i] = (LL)invF[i + 1] * (i + 1) % P;
}
const int G = 3;
const int NUM = 20;
LL wn[NUM];
LL va[MX],vb[MX];
void GetWn()
{
for(int i = 0; i < NUM; i++)
{
int t = 1 << i;
wn[i] = quick_power(G, (P - 1) / t, P);
}
}
void Rader(LL F[], int len)
{
int j = len >> 1;
for(int i = 1; i < len - 1; i++)
{
if(i < j) swap(F[i], F[j]);
int k = len >> 1;
while(j >= k)j -= k,k >>= 1;
if(j < k) j += k;
}
}
void NTT(LL F[], int len, int t)
{
Rader(F, len);
int id = 0;
for(int h = 2; h <= len; h <<= 1)
{
id++;
for(int j = 0; j < len; j += h)
{
LL E = 1;
for(int k = j; k < j + h / 2; k++)
{
LL u = F[k];
LL v = E * F[k + h / 2] % P;
F[k] = (u + v) % P;
F[k + h / 2] = (u - v + P) % P;
E = E * wn[id] % P;
}
}
}
if(t == -1)
{
for(int i = 1; i < len / 2; i++)swap(F[i], F[len - i]);
LL inv = quick_power(len, P - 2, P);
for(int i = 0; i < len; i++)F[i] = F[i] * inv % P;
}
}
void Conv(LL a[], LL b[], int len)
{
NTT(a, len, 1);
NTT(b, len, 1);
for(int i = 0; i < len; i++)a[i] = a[i] * b[i] % P;
NTT(a, len, -1);
}
int dp[MX];
void cdq(int l,int r)
{
if(l==r)
{
dp[l]=(LL)F[l-1]*(dp[l]+(LL)l*l%P)%P;
return ;
}
int mid=(l+r)>>1;
cdq(l,mid);
int len=1;
while(len<mid-2*l+r-1)len<<=1;
for(int i=l; i<=mid; i++)va[i-l]=(LL)dp[i]*invF[i]%P;
for(int i=mid-l+1; i<len; i++)va[i]=0;
for(int i=1; i<=r-l; i++)vb[i-1]=(LL)i*i%P;
for(int i=r-l; i<len; i++)vb[i]=0;
Conv(va,vb,len);
for(int i=mid+1; i<=r; i++)dp[i]=(dp[i]+va[i-l-1])%P;
cdq(mid+1,r);
}
void pre()
{
for(int i=1; i<=100000; i++)dp[i]=0;
cdq(1,100000);
}
int main()
{
GetWn();
init();
pre();
while(cin>>n)cout<<dp[n]<<endl;
return 0;
}
#include<iostream>
#include<cstdio>
#include<math.h>
#include<algorithm>
#include<map>
#include<set>
#include<bitset>
#include<stack>
#include<queue>
#include<string.h>
#include<cstring>
#include<vector>
#include<time.h>
#include<stdlib.h>
using namespace std;
#define INF 0x3f3f3f3f
#define INFLL 0x3f3f3f3f3f3f3f3f
#define FIN freopen("input.txt","r",stdin)
#define mem(x,y) memset(x,y,sizeof(x))
typedef unsigned long long ULL;
typedef long long LL;
#define fuck(x) cout<<"x"<<endl;
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
typedef pair<pair<int,int>,int> PIII;
typedef pair<LL,LL> PII;
const double eps=1e-100;
const int MX=444444;
const int P=998244353;
int n;
LL F[MX],invF[MX];
LL quick_power(LL a, LL x, LL mod) {
LL ans = 1;
a %= mod;
while(x) {
if(x & 1)ans = ans * a % mod;
x >>= 1;
a = a * a % mod;
}
return ans;
}
void init() {
F[0] = 1;
for(int i = 1; i < MX; i++) F[i] = ((LL)F[i - 1] * i) % P;
invF[MX - 1] = quick_power(F[MX - 1],P - 2,P);
for(int i = MX - 2; i >= 0; i--) invF[i] = (LL)invF[i + 1] * (i + 1) % P;
}
struct Complex {
double r,i;
Complex(double r=0,double i=0):r(r),i(i) {};
Complex operator+(const Complex &rhs) {
return Complex(r + rhs.r,i + rhs.i);
}
Complex operator-(const Complex &rhs) {
return Complex(r - rhs.r,i - rhs.i);
}
Complex operator*(const Complex &rhs) {
return Complex(r*rhs.r - i*rhs.i,i*rhs.r + r*rhs.i);
}
} w[MX + 5];
const double PI = acos(-1);
int bitrev[MX + 5];
void fft(Complex *a, const int &n) {
for(int i=0; i<n; i++) if (i < bitrev[i]) swap(a[i], a[bitrev[i]]);
for (int i = 2, lyc = n >> 1; i <= n; i <<= 1, lyc >>= 1)
for (int j = 0; j < n; j += i) {
Complex *l = a + j, *r = a + j + (i >> 1), *p = w;
for(int k=0; k<(i>>1); k++) {
Complex tmp = *r * *p;
*r = *l - tmp, *l = *l + tmp;
++l, ++r, p += lyc;
}
}
}
inline void fft_prepare(int len) {
int L=0;
for ( ; (1 << L) < len; ++L);
for(int i=0; i<len; i++) bitrev[i] = bitrev[i >> 1] >> 1 | ((i & 1) << (L - 1));
for(int i=0; i<len; i++) w[i] = Complex(cos(2 * PI * i / len), sin(2 * PI * i / len));
}
//conv(a, b, c,len);c为答案数组
inline void Conv(int *x, int *y, int *z,int len) {
fft_prepare(len);
for(int i=0; i<len; i++) (x[i] += P) %= P, (y[i] += P) %= P;
static Complex a[MX + 5], b[MX + 5];
static Complex dfta[MX + 5], dftb[MX + 5], dftc[MX + 5], dftd[MX + 5];
for(int i=0; i<len; i++) a[i] = Complex(x[i] & 32767, x[i] >> 15);
for(int i=0; i<len; i++) b[i] = Complex(y[i] & 32767, y[i] >> 15);
fft(a, len), fft(b, len);
for(int i=0; i<len; i++) {
int j = (len - i) & (len - 1);
static Complex da, db, dc, dd;
da = (a[i] + Complex(a[j].r,-a[j].i)) * Complex(0.5, 0);
db = (a[i] - Complex(a[j].r,-a[j].i)) * Complex(0, -0.5);
dc = (b[i] + Complex(b[j].r,-b[j].i)) * Complex(0.5, 0);
dd = (b[i] - Complex(b[j].r,-b[j].i)) * Complex(0, -0.5);
dfta[j] = da * dc;
dftb[j] = da * dd;
dftc[j] = db * dc;
dftd[j] = db * dd;
}
for(int i=0; i<len; i++) a[i] = dfta[i] + dftb[i] * Complex(0, 1);
for(int i=0; i<len; i++) b[i] = dftc[i] + dftd[i] * Complex(0, 1);
fft(a, len), fft(b, len);
for(int i=0; i<len; i++) {
int da = (LL)(a[i].r / len + 0.5) % P;
int db = (LL)(a[i].i / len + 0.5) % P;
int dc = (LL)(b[i].r / len + 0.5) % P;
int dd = (LL)(b[i].i / len + 0.5) % P;
z[i] = (da + ((LL)(db + dc) << 15) + ((LL)dd << 30)) % P;
}
for(int i=0; i<len; i++) (z[i] += P) %= P;
}
int dp[MX];
int a[MX],b[MX],c[MX];
void cdq(int l,int r) {
if(l==r) {
dp[l]=(LL)F[l-1]*(dp[l]+(LL)l*l%P)%P;
return ;
}
int mid=(l+r)>>1;
cdq(l,mid);
int len=1;
while(len<mid-2*l+r-1)len<<=1;
for(int i=l; i<=mid; i++)a[i-l]=(LL)dp[i]*invF[i]%P;
for(int i=mid-l+1; i<len; i++)a[i]=0;
for(int i=1; i<=r-l; i++)b[i-1]=(LL)i*i%P;
for(int i=r-l; i<len; i++)b[i]=0;
Conv(a,b,c,len);
for(int i=mid+1; i<=r; i++)dp[i]=(dp[i]+c[i-l-1])%P;
cdq(mid+1,r);
}
void pre() {
for(int i=1; i<=100000; i++)dp[i]=0;
cdq(1,100000);
}
int main() {
FIN;
init();
pre();
while(cin>>n)cout<<dp[n]<<endl;
return 0;
}