• 进军多项式(三):Chirp Z-Transform


    Chirp Z-Transform

    题目传送门
    给定一个n次多项式 F ( x ) F(x) F(x),对于 i = 0 i=0 i=0 m m m查询 F ( c i ) F(c^i) F(ci)
    c c c为常数。

    我们推一下式子,
    a n s i = ∑ j = 0 n − 1 f j c i j ans_i=\sum_{j=0}^{n-1}f_jc^{ij} ansi=j=0n1fjcij
    注意到:
    i j = C i + j 2 − C i 2 − C j 2 ij=C_{i+j}^2-C_i^2-C_j^2 ij=Ci+j2Ci2Cj2
    a n s i = ∑ j = 0 n − 1 f j c C i + j 2 − C i 2 − C j 2 ans_i=\sum_{j=0}^{n-1}f_jc^{C_{i+j}^2-C_i^2-C_j^2} ansi=j=0n1fjcCi+j2Ci2Cj2
    提取 C i 2 C_i^2 Ci2
    a n s i = ∑ j = 0 n − 1 f j c C i + j 2 − C i 2 − C j 2 ans_i=\sum_{j=0}^{n-1}f_jc^{C_{i+j}^2-C_i^2-C_j^2} ansi=j=0n1fjcCi+j2Ci2Cj2
    a n s i = c − C i 2 ∑ j = 0 n − 1 f j c C i + j 2 − C j 2 ans_i=c^{-C_i^2}\sum_{j=0}^{n-1}f_jc^{C_{i+j}^2-C_j^2} ansi=cCi2j=0n1fjcCi+j2Cj2
    右边的式子只和 j , i + j j,i+j j,i+j有关,差卷积即可。
    复杂度 O ( ( n + m ) log ⁡ ( m + n ) ) O((n+m)\log (m+n)) O((n+m)log(m+n))

    #include
    using namespace std;
    const int N = 8e6+7;
    int w[2][N];
    int lim;
    typedef long long LL;
    const int mod = 998244353;
    int Pow(int a,int b)
    {
    	int res=1;
    	while(b)
    	{
    		if(b&1)res=1ll*res*a%mod;
    		a=1ll*a*a%mod;
    		b>>=1;
    	}
    	return res;
    } 
    int G=3,IG=(mod+1)/G;
    int o[2];
    void init(int n)
    {
    	lim=1;
    	while(lim<=n) lim<<=1;
    	o[0]=Pow(G,(mod-1)/lim);
    	o[1]=Pow(IG,(mod-1)/lim);
    	for(int d=0;d<2;d++)
    	{
    		w[d][0]=1;
    		for(int i=1;i<(lim>>1);i++)
    		w[d][i]=1ll*w[d][i-1]*o[d]%mod;
    	}
    }
    inline void DFT(int *f)
    {
    	for(int k=lim,l=k>>1,r=1;k>=2;k>>=1,l>>=1,r<<=1)
    	for(int i=0;i<lim;i+=k)
    	for(int j=i,p=0;p<l;j++,p++)
    	{
    		int u=f[j],v=f[j+l]%mod;
    		f[j]=(u+v)%mod;
    		f[j+l]=1ll*w[0][p*r]*(u-v+mod)%mod;
    	}
    } 
    inline void IDFT(int *f)
    {
    	for(int k=2,l=1,r=(lim>>1);k<=lim;k<<=1,l<<=1,r>>=1)
    	for(int i=0;i<lim;i+=k)
    	for(int j=i,p=0;p<l;j++,p++)
    	{
    		int u=f[j],v=1ll*w[1][p*r]*f[j+l]%mod;
    		f[j]=(u+v)%mod;
    		f[j+l]=(u-v+mod)%mod;
    	}	
    	int inv=Pow(lim,mod-2);
    	for(int i=0;i<lim;i++)
    	f[i]=1ll*f[i]*inv%mod;
    }
    int n,m,c;
    int f[N],g[N];
    inline int C(int x)
    {
    	return 1ll*x*(x-1)/2%(mod-1);
    }
    int main()
    {
    	cin>>n>>c>>m;
    	init((n+m-1)<<1);
    	for(int i=0;i<n;i++)
    	{
    		scanf("%d",&f[i]);
    		f[i]=1ll*f[i]*Pow(c,mod-1-C(i))%mod;
    	}
    	for(int i=0;i<n+m;i++)
    	g[i]=Pow(c,C(i))%mod;
    	reverse(f,f+n);
    	DFT(f);DFT(g);
    	for(int i=0;i<lim;i++)
    	f[i]=1ll*f[i]*g[i]%mod;
    	IDFT(f);
    	for(int i=0;i<m;i++)
    	printf("%lld ",1ll*f[n+i-1]*Pow(c,mod-1-C(i))%mod);
    
    	return 0;
    }
    

    例题

    任意模数Chirp Z-Transform

    把NTT换成MTT或者三模NTT就好了。
    但是注意实现的细节,这玩意卡时间也卡空间。

    CF1054H Epic Convolution

    A i = ∑ j = 0 [ j 2 ≡ i (mod 490018) ] a j A_i=\sum_{j=0}[j^2\equiv i \text{(mod 490018)}]a_j Ai=j=0[j2i(mod 490018)]aj, B i = ∑ j = 0 [ j 3 ≡ i (mod 490018) ] b j B_i=\sum_{j=0}[j^3\equiv i \text{(mod 490018)} ]b_j Bi=j=0[j3i(mod 490018)]bj
    这里上界减一是因为扩展欧拉定理。
    那么答案即为
    ∑ i = 0 490017 ∑ j = 0 490017 A i B j c i j \sum_{i=0}^{490017}\sum_{j=0}^{490017}A_iB_jc^{ij} i=0490017j=0490017AiBjcij
    提取 i i i
    ∑ i = 0 490017 A i ∑ j = 0 490017 B j c i j \sum_{i=0}^{490017}A_i\sum_{j=0}^{490017}B_jc^{ij} i=0490017Aij=0490017Bjcij
    F ( x ) = ∑ i B i x i F(x)=\sum_i B_ix^i F(x)=iBixi
    那么就是

    ∑ i = 0 490017 A i F ( c i ) \sum_{i=0}^{490017}A_i F(c^i) i=0490017AiF(ci)
    上板子就好了。
    但是要写任模。

    拓展

    Bluestein’s Algorithm \text{Bluestein’s Algorithm} Bluestein’s Algorithm

  • 相关阅读:
    MySQL 8.0安装及配置教程
    java-net-php-python-ssm巴音学院餐饮安全与卫生防御管理系统计算机毕业设计程序
    Flask三种添加路由的方法
    【Git从青铜到王者】第一篇:Git引言
    基于Springboot+MySQL的个人健康监控管理系统
    【毕业设计】30-基于单片机矿井瓦斯_气体浓度_烟雾浓度报警设计(原理图+源代码+仿真+答辩论文+答辩PPT)
    深入React源码揭开渲染更新流程的面纱
    华为机试真题 C++ 实现【绘图机器】【计算面积】
    论文阅读-可泛化深度伪造检测的关键
    当我们谈论DDD时我们在谈论什么
  • 原文地址:https://blog.csdn.net/jwg2732/article/details/126962320