luogu P4245(任意模數ntt)

題目鏈接:https://www.luogu.org/problem/P4245

思路:模板題

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <bitset>
#include <cmath>
#include <cctype>
#include <iostream>
#include <algorithm>
#include <string>
#include <vector>
#include <queue>
#include <map>
#include <set>
#include <sstream>
#include <iomanip>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const ll inff = 0x3f3f3f3f3f3f3f3f;
#define FOR(i,a,b) for(int i(a);i<=(b);++i)
#define FOL(i,a,b) for(int i(a);i>=(b);--i)
#define REW(a,b) memset(a,b,sizeof(a))
#define inf int(0x3f3f3f3f)
#define si(a) scanf("%d",&a)
#define sl(a) scanf("%lld",&a)
#define sd(a) scanf("%lf",&a)
#define ss(a) scanf("%s",a)
//#define mod ll(1e9+7)
#define pb push_back
#define db long double
#define eps 1e-6
#define lc d<<1
#define rc d<<1|1
#define Pll pair<ll,ll>
#define Pii pair<int,int>
#define pi acos(-1)
const int N=1e6+8;
ll n,m,l,r,A[N],B[N],mod,deg1,deg2;
struct CP{
    db x,y;
    CP(){} CP(db a,db b):x(a),y(b){}
    CP operator+(const CP&r) const{return CP(x+r.x,y+r.y);}
    CP operator-(const CP&r) const{return CP(x-r.x,y-r.y);}
    CP operator*(const CP&r) const{return CP(x*r.x-y*r.y,x*r.y+y*r.x);}
}a[N],b[N],a1[N],b1[N],c1[N],c2[N],c3[N];
inline void FFT(CP a[],int f,int n)
{
    int i,j,k;
    for(i=j=0;i<n;i++)
    {
        if(i>j) swap(a[i],a[j]);
        for(k=n>>1;(j^=k)<k;k>>=1);
    }
    for (int d=0;(1<<d)<n;d++)
    {
        int m=1<<d,m2=m<<1;
        db o=pi*2/m2*f;
        CP _w(cos(o),sin(o));
        for (int i=0;i<n;i+=m2)
        {
            CP w(1,0);
            FOR(j,0,m-1)
            {
                CP &A=a[i+j+m],&B=a[i+j],t=w*A;
                A=B-t;B=B+t;w=w*_w;
            }
        }
    }
    if(f==-1) FOR(i,0,n) a[i].x/=n;
}
int main()
{
    cin.tie(0);
    cout.tie(0);
    while(cin>>deg1>>deg2>>mod)
    {
        deg1++,deg2++;
        FOR(i,0,deg1-1) sl(A[i]);
        FOR(i,0,deg2-1) sl(B[i]);
        for(int i=0;i<deg1;i++) a1[i].x=A[i]>>15;
        for(int i=0;i<deg2;i++) b1[i].x=B[i]>>15;
        for(int i=0;i<deg1;i++) a[i].x=A[i]&0x7FFF;
        for(int i=0;i<deg2;i++) b[i].x=B[i]&0x7FFF;
        for(deg2=deg2+deg1,deg1=1;deg1<=deg2;deg1<<=1);
        //  cout<<deg1<<endl;
        FFT(a1,1,deg1);FFT(b1,1,deg1);FFT(a,1,deg1);FFT(b,1,deg1);
        for(int i=0;i<deg1;i++)
        {
            c1[i]=a1[i]*b1[i];
            c2[i]=a1[i]*b[i]+a[i]*b1[i];
            c3[i]=a[i]*b[i];
        }
        FFT(c1,-1,deg1);FFT(c2,-1,deg1);FFT(c3,-1,deg1);
        ll sum=0;
        FOR(i,0,deg2-2)
         printf("%lld ",(((ll)round(c1[i].x)%mod<<30)%mod+((ll)round(c2[i].x)%mod<<15)%mod+(ll)round(c3[i].x)%mod)%mod);
        puts("");
    }
    return 0;
}
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <bitset>
#include <cmath>
#include <cctype>
#include <iostream>
#include <algorithm>
#include <string>
#include <vector>
#include <queue>
#include <map>
#include <set>
#include <sstream>
#include <iomanip>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const ll inff = 0x3f3f3f3f3f3f3f3f;
#define FOR(i,a,b) for(int i(a);i<=(b);++i)
#define FOL(i,a,b) for(int i(a);i>=(b);--i)
#define REW(a,b) memset(a,b,sizeof(a))
#define inf int(0x3f3f3f3f)
#define si(a) scanf("%d",&a)
#define sl(a) scanf("%lld",&a)
#define sd(a) scanf("%lf",&a)
#define ss(a) scanf("%s",a)
//#define mod ll(1e9+7)
#define pb push_back
#define eps 1e-6
#define lc d<<1
#define rc d<<1|1
#define Pll pair<ll,ll>
#define Pii pair<int,int>
#define pi acos(-1)
const int N=2e6+8;
ll n,m,l,r,a[N],b[N],R[N],B[N],mod;
ll gmod(ll a,ll b,ll p)
{
    ll res=1;
    while(b)
    {
        if(b&1) res=res*a%p;
        a=a*a%p;b>>=1;
    }
    return res;
}
ll pr[]={469762049,998244353,1004535809};
struct FFT{
    ll G,P,A[N];
    void NTT(ll* a,int f,int n)
    {
        FOR(i,0,n-1) if(i<R[i]) swap(a[i],a[R[i]]);
        for(int i=1;i<n;i<<=1){
            ll gn=gmod(G,(P-1)/(i<<1),P);
            for(int j=0;j<n;j+=(i<<1)){
                ll g=1;
                for(int k=0;k<i;k++,g=1ll*g*gn%P){
                    ll x=a[j+k],y=1ll*g*a[j+k+i]%P;
                    a[j+k]=(x+y)%P;a[j+k+i]=(x-y+P)%P;
                }
            }
        }
        if(f==1) return;
        ll nv=gmod(n,P-2,P);reverse(a+1,a+n);
        FOR(i,0,n-1) a[i]=1ll*a[i]*nv%P;
    }
}fft[3];
int deg1,deg2,deg;
ll ans[N];
ll inv(ll n,ll p){return gmod(n%p,p-2,p);}
ll mul(ll a,ll b,ll p){return (a*b-(ll)((long double)a/p*b)*p+p)%p;}
void CRT()
{
    deg=deg1+deg2;
    ll a,b,c,t,k,M=1ll*pr[0]*pr[1];
    ll inv1=inv(pr[1],pr[0]),inv0=inv(pr[0],pr[1]),inv3=inv(M%pr[2],pr[2]);
    FOR(i,0,deg)
    {
        a=fft[0].A[i],b=fft[1].A[i],c=fft[2].A[i];
        t=(mul(a*pr[1]%M,inv1,M)+mul(b*pr[0]%M,inv0,M))%M;
        k=((c-t%pr[2])%pr[2]+pr[2])%pr[2]*inv3%pr[2];
        ans[i]=((k%mod)*(M%mod)%mod+t%mod)%mod;
    }
}
void conv()
{
    ll L=0;n=deg1,m=deg2;
    m=n+m;for(n=1;n<=m;n<<=1) L++;
    FOR(i,0,n-1) R[i]=(R[i>>1]>>1)|((i&1)<<(L-1));
    FOR(u,0,2)
    {
        fft[u].G=3;fft[u].P=pr[u];
        FOR(i,0,deg1-1) fft[u].A[i]=a[i];
        FOR(i,0,deg2-1) B[i]=b[i];
        FOR(i,deg1,n) fft[u].A[i]=0;
        FOR(i,deg2,n) B[i]=0;
        fft[u].NTT(fft[u].A,1,n);fft[u].NTT(B,1,n);
        FOR(i,0,n-1) fft[u].A[i]=fft[u].A[i]*B[i]%pr[u];
        fft[u].NTT(fft[u].A,-1,n);
    }
}
int main()
{
    cin.tie(0);
    cout.tie(0);
    while(cin>>deg1>>deg2>>mod)
    {
        deg1++,deg2++;
        FOR(i,0,deg1-1) sl(a[i]);
        FOR(i,0,deg2-1) sl(b[i]);
        ll sum=0;
        conv(),CRT();
        FOR(i,0,deg-2) printf("%lld ",ans[i]);
        puts("");
    }
    return 0;
}

 

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