NesCafe41 异化多肽 NTT实现多项式求逆

题意:

并没有链接。

方法: NTT实现多项式求逆

解析:

首先,这个质数….

它的最小原根是5…

这个实现一下下就好辣。

但是大爷有个神奇的方法。

检验你是欧洲人还是非洲人的方法。

你大可以随便蒙一个数是它的原根。

一个数的原根大概有Phi(Phi(x))个。

所以检验脸黑还是脸白的时候到了!

然后呢这个题比较显然了。

选0个 -> F0x

选1个 -> F1(x)

选2个 -> F2(x)

选3个 -> F3(x)

….

所以答案就是 1F(x)1F(x) mod xn

所以 F(x) 这一项没有贡献,省略。

于是答案变成了 11F(x) mod xn 的n次项系数..

所以就是个普通的多项式求逆嘛..

多项式怎么求逆呢?

递归搞阿。

假设 F(x)G(x)=1 (mod xn)

现在我们要求出来H(x)使得

F(x)H(x)=1 (mod x2n)

以下为推导..

F(x)G(x)1=0 (mod xn)

F2(x)G2(x)2F(x)G(x)+1=0 (mod x2n)

两边同乘以H(x)

F(x)G2(x)2G(x)+H(x)=0 (mod x2n)

H(x)=2G(x)F(x)G2(x) (mod x2n)

H(x)=G(x)(2F(x)G(x)) (mod x2n)

所以三遍NTT就行辣!

复杂度?

T(n)=O(nlogn)+T(n/2)=O(nlogn)

代码:

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define N 524288
#define mod 1005060097
//1005060097->primitive_root is 5
using namespace std;
typedef long long ll;
int n,t,primitive_root;
ll f[N];
ll t1[N],t2[N],temp[N];
int rev[N];
ll Quick_Power(ll x,ll y,ll MOD)
{
    ll ret=1;
    while(y)
    {
        if(y&1)ret=(ret*x)%MOD;
        x=(x*x)%MOD;
        y>>=1;
    }
    return ret;
}
void NTT(ll *a,int len,int f)
{
    for(int i=0;i<len;i++)if(i<rev[i])swap(a[i],a[rev[i]]);
    for(int h=2;h<=len;h<<=1)
    {
        ll wn=Quick_Power(primitive_root,(mod-1)/h,mod);
        for(int i=0;i<len;i+=h)
        {
            ll w=1;
            for(int j=0;j<(h>>1);j++,w=w*wn%mod)
            {
                ll t=a[i+j+(h>>1)]*w%mod;
                a[i+j+(h>>1)]=((a[i+j]-t)%mod+mod)%mod;
                a[i+j]=(a[i+j]+t)%mod;
            }
        }
    }
    if(f==-1)
    {
        for(int i=1;i<(len>>1);i++)swap(a[i],a[len-i]);
        ll inv=Quick_Power(len,mod-2,mod);
        for(int i=0;i<len;i++)a[i]=a[i]*inv%mod;
    } 
}
void Get_Inv(ll *a,ll *b,int n)
{
    if(n==1)
    {
        b[0]=Quick_Power(a[0],mod-2,mod);
        return ;
    }
    Get_Inv(a,b,n>>1);
    memcpy(temp,a,sizeof(a[0])*n);
    int m=n,L=0,nn=n;
    for(n=1;n<=m;n<<=1)L++;
    for(int i=0;i<n;i++)rev[i]=(rev[i>>1]>>1)|((i&1)<<(L-1));
    NTT(temp,n,1),NTT(b,n,1);
    for(int i=0;i<n;i++)
        temp[i]=(b[i]*(((2-temp[i]*b[i]%mod)%mod+mod)%mod))%mod;
    NTT(temp,n,-1);
    for(int i=0;i<(n>>1);i++)b[i]=temp[i];
    memset(b+nn,0,sizeof(b[0])*nn);
    n=nn;
}
int main()
{
    scanf("%d%d",&n,&t);
    for(int i=1;i<=t;i++)
    {
        ll x;
        scanf("%lld",&x);
        f[x]++;
    }
    f[0]=((1-f[0])%mod+mod)%mod;
    for(int i=1;i<=n;i++)
        f[i]=((-f[i])%mod+mod)%mod;
    memcpy(t1,f,sizeof(f));
    primitive_root=rand()%140345+1;
    int l;
    for(l=1;l<=n;l<<=1);
    Get_Inv(t1,t2,l);
    printf("%lld\n",t2[n]);
}

你可能感兴趣的:(X,欧洲,ntt,phi)