HDU6061 RXD and functions

題目鏈接

題意

​ 已知 f(x)=ni=0cixi ,給定一個長度爲 m 的數列 A ,求 f(xmi=1ai) 的所有係數模998244353的結果。

分析

​ 賽時糾結其它題去了,沒有認真推=-=。(雖然推出來了,當時也沒有NTT的板子的說)

​ 以下均用 a 代替 mi=1ai

​ 將所有的 (xa)i 均拆開,並將對應 xi 的係數劃分到一塊,得到

f(xa)=i=0nxi(j=incjCijaji)

​ 再將組合數部分拆開得到

i=0nxi(j=incjj!(ji)!i!aji)

​ 爲了便於計算,將 jj+i 進行替換,得到

i=0nxi(j=0nicj+i(j+i)!j!i!aj)

​ 將內層求和中無關的變量i的部分提出,並進行簡單的劃分得到

i=0nxii!(j=0ni(cj+i(j+i)!)(ajj!))

​ 向卷積式湊一下,令 k=nij ,再進行一次替換得到

i=0nxii!(j+k=ni(cnk(nk)!)(ajj!))

​ 將 cnk(nk)! 在n長度進行一個翻轉就能將式子轉換成卷積式,再就是套一下NTT即可,具體可以看代碼。

代碼

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define Mp(x,y) make_pair(x,y)
#define LL long long
#define MAXN 100100
const int inf = 0x3fffffff;
const int mmax  = 1<<18;
const int mod = 998244353;
const int g = 3;  //原根
LL quick_mod(LL a,LL b){
    LL ans=1;  
    for(;b;b/=2){
        if(b&1)  
            ans=ans*a%mod;  
        a=a*a%mod;  
    }  
    return ans;  
}  
int rev(int x,int r)  //蝴蝶操作  
{  
    int ans=0;  
    for(int i=0; i<r; i++){
        if(x&(1<<i)){
            ans+=1<<(r-i-1);  
        }  
    }  
    return ans;  
}  
void NTT(int n,LL A[],int on) // 長度爲N (2的次數)   
{  
    int r=0;  
    for(;; r++){
        if((1<<r)==n)  
            break;  
    }  
    for(int i=0; i<n; i++){
        int tmp=rev(i,r);
        if(i<tmp)  
            swap(A[i],A[tmp]);  
    }  
    for(int s=1; s<=r; s++){
        int m=1<<s;  
        LL wn=quick_mod(g,(mod-1)/m);
        for(int k=0; k<n; k+=m){
            LL  w=1;
            for(int j=0; j<m/2; j++){
                LL t,u;  
                t=w*(A[k+j+m/2]%mod)%mod;  
                u=A[k+j]%mod;  
                A[k+j]=(u+t)%mod;  
                A[k+j+m/2]=((u-t)%mod+mod)%mod;  
                w=w*wn%mod;  
            }  
        }  
    }  
    if(on==-1){
        for(int i=1;i<n/2;i++)  
            swap(A[i],A[n-i]);  
        LL inv=quick_mod(n,mod-2);  
        for(int i=0;i<n;i++)  
            A[i]=A[i]%mod*inv%mod;  
    }  

}  
LL A[mmax+10],B[mmax+10];  
LL ans[mmax+10];
int c[MAXN];
LL fac[MAXN];
LL ni[MAXN];
void init(){
    fac[0]=ni[0]=1;
    for(int i=1;i<MAXN;++i)
        fac[i]=(fac[i-1]*i)%mod;
    ni[MAXN-1]=quick_mod(fac[MAXN-1],mod-2);
    for(int i=MAXN-2;i;i--)
        ni[i]=(ni[i+1]*(i+1))%mod;
}
int main(){
    int n,m,tmp;
    init();
    while(~scanf("%d",&n)){
        LL a=0;
        for(int i=0;i<=n;++i)
            scanf("%d",&c[i]);
        scanf("%d",&m);
        for(int i=0;i<m;++i){
            scanf("%d",&tmp);
            a-=tmp;
            if(a<0)
                a+=mod;
        }
        if(a==0){
            for(int i=0;i<=n;++i)
                printf("%d ",c[i]);
            cout<<endl;
            continue;
        }
        B[0]=1;
        LL aa=1;
        int l=1;
        while(l<=2*n)
            l<<=1;
        for(int i=0;i<l;++i){
            if(i<=n){
                A[i]=(fac[n-i]*c[n-i])%mod;
                B[i]=(aa*ni[i])%mod;
            }
            else
                A[i]=B[i]=0;
            aa=(aa*a)%mod;
        }
        NTT(l,A,1);
        NTT(l,B,1);
        for(int i=0; i<l; i++)
            A[i]=A[i]*B[i]%mod;  
        NTT(l,A,-1);
        for(int i=0;i<=n;++i)
            printf("%I64d ",(A[n-i]*ni[i])%mod);
        cout<<endl;
    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章