zoukankan      html  css  js  c++  java
  • UOJ 34 多项式乘法 ——NTT

    【题目分析】

        快速数论变换的模板题目。

        与fft的方法类似,只是把复数域中的具有循环性质的单位复数根换成了模意义下的原根。

        然后和fft一样写就好了,没有精度误差,但是跑起来比较慢。

        这破题目改了好长时间,吃枣药丸。

    【代码】

    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    using namespace std;
    const int md=998244353;
    const int g=3;
    #define F(i,j,k) for (int i=j;i<=k;++i)
    #define D(i,j,k) for (int i=j;i>=k;--i)
    #define ll long long 
    #define maxn 400005
    int n,m,rev[maxn],len=0,top;
    int a[maxn],b[maxn],c[maxn];
    
    int _pow(int a,int b)
    {
    	int ret=1;
    	while (b)
    	{
    		if (b&1) ret=(ll)ret*a%md;
    		a=(ll)a*a%md;
    		b>>=1;
    	}
    	return ret;
    }
    
    void NTT(int * x,int n,int f)
    {
    	F(i,0,n-1) if (rev[i]>i) swap(x[i],x[rev[i]]);
    	for (int m=2;m<=n;m<<=1)
    	{
    		int wn=_pow(g,(md-1)/m);
    		if (f) wn=_pow(wn,md-2);
    		for (int i=0;i<n;i+=m)
    		{
    			int w=1;
    			F(j,0,(m>>1)-1)
    			{
    				int u=x[i+j],v=(ll)x[i+j+(m>>1)]*w%md;
    				x[i+j]=(u+v)%md;
    				x[i+j+(m>>1)]=((u-v)%md+md)%md;
    				w=(ll)w*wn%md;
    			}
    		}
    	}
    }
    
    int main()
    {
    	scanf("%d%d",&n,&m);
    	F(i,0,n) scanf("%d",&a[i]);
    	F(i,0,m) scanf("%d",&b[i]);
    	n=n+m+1;m=1;
    	top=n+m-1;
    	while (m<=n) m<<=1,len++; n=m;
    	F(i,0,n-1)
    	{
    		int ret=0,t=i;
    		F(j,1,len) ret<<=1,ret|=t&1,t>>=1;
    		rev[i]=ret;
    	}
    	NTT(a,n,0); NTT(b,n,0);
    	F(i,0,n-1) c[i]=(ll)a[i]*b[i]%md;
    	NTT(c,n,1);
    	int tmp=_pow(n,md-2);
    	F(i,0,top-1) printf("%d ",(ll)c[i]*tmp%md);
    }
    

      

  • 相关阅读:
    java
    MVC4重复提交数据
    cache
    Nosql
    MVC4重复提交
    PHP Java
    .net performance
    How the Runtime Locates Assemblies
    android
    window.onscroll
  • 原文地址:https://www.cnblogs.com/SfailSth/p/6422532.html
Copyright © 2011-2022 走看看