• bzoj 2194: 快速傅立叶之二【NTT】


    看别的blog好像我用了比较麻烦的方法……
    (以下的n都--过

    [c[i]=sum_{j=i}^{n}a[i]*b[j-i] ]

    设j=i+j

    [c[i]=sum_{j=0}^{n-i}a[i+j]*b[i+j-i] ]

    [c[i]=sum_{j=0}^{n-i}a[i+j]*b[j] ]

    再设j=n-i-j

    [c[i]=sum_{n-i-j}^{n-i}a[n-i-j+i]b[n-i-j] ]

    [n-i-j geq 0 Rightarrow j leq n-i ]

    [n-i-j<=n-i Rightarrow j geq 0 ]

    [c[i]=sum_{j=0}^{n-i}a[n-j]b[n-i-j] ]

    然后把n-i和i换一下

    [c[n-i]=sum_{j=0}^{i}a[n-j]b[i-j] ]

    至此,只有a看起来不是卷积,于是可以在读入的时候就把a数组翻转(读入b[i],a[n-i]即可)
    然后注意c也是反转的,输出的时候倒着输出

    #include<iostream>
    #include<cstdio>
    #include<cmath>
    using namespace std;
    const int mod=998244353,G=3,N=5e6;
    int lm,bt,n,re[N],ans[N],a[N],b[N];
    int read()
    {
    	int r=0,f=1;
    	char p=getchar();
    	while(p>'9'||p<'0')
    	{
    		if(p=='-')
    			f=-1;
    		p=getchar();
    	}
    	while(p>='0'&&p<='9')
    	{
    		r=r*10+p-48;
    		p=getchar();
    	}
    	return r*f;
    }
    int ksm(int a,int b)
    {
    	int r=1;
    	while(b)
    	{
    		if(b&1)
    			r=1ll*r*a%mod;
    		a=1ll*a*a%mod;
    		b>>=1;
    	}
    	return r;
    }
    void dft(int a[],int f)
    {
    	for(int i=0;i<lm;i++)
    		if(i<re[i])
    			swap(a[i],a[re[i]]);
    	for(int i=1;i<lm;i<<=1)
    	{
    		int wi=ksm(G,(mod-1)/(i*2));
    		if(f==-1)
    			wi=ksm(wi,mod-2);
    		for(int k=0;k<lm;k+=(i<<1))
    		{
    			int w=1,x,y;
    			for(int j=0;j<i;j++)
    			{
    				x=a[k+j];
    				y=1ll*w*a[k+j+i]%mod;
    				a[k+j]=((x+y)%mod+mod)%mod;
    				a[k+j+i]=((x-y)%mod+mod)%mod;
    				w=1ll*w*wi%mod;
    			}
    		}
    	}
    	if(f==-1)
    	{
    		int inv=ksm(lm,mod-2);
    		for(int i=0;i<lm;i++)
    			a[i]=1ll*a[i]*inv%mod;
    	}
    }
    void ntt()
    {
    	bt=1;
    	for(;(1<<bt)<=2*n;bt++);
    	lm=(1<<bt);
    	for(int i=0;i<=lm;i++)
    		re[i]=(re[i>>1]>>1)|((i&1)<<(bt-1));
    	dft(a,1);
    	dft(b,1);
    	for(int i=0;i<lm;i++)
    		a[i]=1ll*a[i]*b[i]%mod;
    	dft(a,-1);
    }
    int main()
    {
    	n=read();
    	n--;
    	for(int i=0;i<=n;i++)
    		a[n-i]=read(),b[i]=read();
    	ntt();
    	for(int i=n;i>=0;i--)
    		printf("%d
    ",a[i]);
    	return 0;
    }
    
  • 相关阅读:
    win7下安装memcached
    Integer自动装拆箱
    XShell配色方案
    XShell上传和下载
    基于注解的Spring AOP拦截含有泛型的DAO
    PAT Advance 1020
    PAT Advance 1014
    JavaWeb中文乱码问题解决思路
    eclipse启动错误
    操作系统(一)
  • 原文地址:https://www.cnblogs.com/lokiii/p/8473466.html
Copyright © 2020-2023  润新知