HDU - 5322 Hope cdq分治+ntt

題目鏈接點這裏


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;
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章