HDU-6061(NTT)

HDU-6061(NTT)

問題の意味:指定された\(f(x)が\)を求める\(F(XT)\) の係数\(998244353 \)モジュロ

実際には、自然界にはまだ建設畳み込みであります

\ [F(X)= \和a_ix ^ I \]

\ [F(XT)= \和a_iを(XT)^ I \]

\((XT)^ iが\ ) 、我々は得ることが二項定理を展開直接暴力を使用することができる\(F(XT)= \和a_iC(i、j)のtは^ {IJ} X ^ Jを\)

各検討\(I \)のそれぞれについて、(J \)\寄与が組み合わせの数の形、すなわち、である\(\ FRAC {I!} {J!(IJ)!} \) 見ることができ、その差を関連、コンボリューションすることができますので、

初期シーケンスが乗じため\(I!\) 転送シーケンス\({)の(IJ!} \ \ FRAC {}のT ^ {IJ}) 得られた配列を乗じ\(\ FRAC {1 } {J!} \)

#include<bits/stdc++.h>
using namespace std;

//#define double long double

#define reg register
typedef long long ll;
#define rep(i,a,b) for(reg int i=a,i##end=b;i<=i##end;++i)
#define drep(i,a,b) for(reg int i=a,i##end=b;i>=i##end;--i)

template <class T> inline void cmin(T &a,T b){ ((a>b)&&(a=b)); } 
template <class T> inline void cmax(T &a,T b){ ((a<b)&&(a=b)); } 
//#define double long double

char IO;
int rd(){
    int s=0,f=0;
    while(!isdigit(IO=getchar())) if(IO=='-') f=1;
    do s=(s<<1)+(s<<3)+(IO^'0');
    while(isdigit(IO=getchar()));
    return f?-s:s;
}

const double PI=acos(-1);

const int N=(1<<18)+4,P=998244353;
const int g=3;

bool be;
int n,m;
ll a[N],b[N];
int rev[N];

ll qpow(ll x,ll k){ 
    ll res=1;
    for(;k;k>>=1,x=x*x%P) if(k&1) res=res*x%P;
    return res;
}

void NTT(int n,ll *a,int f){
    rep(i,0,n-1) if(i<rev[i]) swap(a[i],a[rev[i]]);
    for(reg int i=1;i<n;i<<=1) {
        ll w=qpow(f==1?3:(P+1)/3,(P-1)/i/2);
        for(reg int l=0;l<n;l+=i*2) {
            ll e=1;
            for(reg int j=l;j<l+i;j++,e=e*w%P) {
                ll t=a[j+i]*e%P;
                a[j+i]=(a[j]-t)%P;
                a[j]=(a[j]+t)%P;
            }
        }
    }
    if(f==-1) {
        ll base=qpow(n,P-2);
        rep(i,0,n-1) a[i]=a[i]*base%P;
    }
}

ll Inv[N],Fac[N],Pow[N];



bool ed;
int main(){
    Inv[0]=Inv[1]=Fac[0]=Fac[1]=1;
    rep(i,2,N-1) {
        Inv[i]=(P-P/i)*Inv[P%i]%P;
        Fac[i]=Fac[i-1]*i%P;
    }
    rep(i,1,N-1) Inv[i]=Inv[i-1]*Inv[i]%P;
    while(~scanf("%d",&n)) {
        rep(i,0,n) a[i]=rd()*Fac[i]%P;//初始序列
        int R=1,c=-1;
        while(R<=n*2) R<<=1,c++;
        rep(i,1,R) rev[i]=(rev[i>>1]>>1)|((i&1)<<c);
        ll x=0;
        rep(i,1,m=rd()) x=(x+rd())%P;//读入t
        x=-x;
        Pow[0]=1;
        rep(i,1,R) Pow[i]=Pow[i-1]*x%P;
        rep(i,0,n) b[n-i]=Pow[i]*Inv[i]%P;//转移序列
        NTT(R,a,1),NTT(R,b,1);
        rep(i,0,R) a[i]=a[i]*b[i]%P;
        NTT(R,a,-1);
        rep(i,0,n) printf("%lld ",(a[i+n]*Inv[i]%P+P)%P); puts(""); //最终处理
        rep(i,0,R) a[i]=b[i]=0;
    }
}



おすすめ

転載: www.cnblogs.com/chasedeath/p/12098078.html