zoukankan      html  css  js  c++  java
  • luoguP4721 【模板】分治 FFT

    P4721 【模板】分治 FFT

    链接

    luogu

    题目描述

    给定长度为 (n-1) 的数组 (g[1],g[2],..,g[n-1]),求 (f[0],f[1],..,f[n-1]),其中

    [f[i]=sum_{j=1}^if[i-j]g[j] ]

    边界为 (f[0]=1) 。答案模 (998244353)

    思路

    分治+ntt。跑900+ms
    其实limit只要设到区间长度就可以了,其他的是用不到的。对前半部分也没得影响。

    代码

    #include <bits/stdc++.h>
    using namespace std;
    const int N=4e5+7,mod=998244353;
    int read() {
    	int x=0,f=1;char s=getchar();
    	for(;s>'9'||s<'0';s=getchar()) if(s=='-') f=-1;
    	for(;s>='0'&&s<='9';s=getchar()) x=x*10+s-'0';
    	return x*f;
    }
    int n,len_a,len_b,p,limit;
    int f[N],g[N],a[N],b[N],r[N];
    int q_pow(int a,int b) {
    	int ans=1;
    	while(b) {
    		if(b&1) ans=1LL*ans*a%mod;
    		a=1LL*a*a%mod;
    		b>>=1;
    	}
    	return ans;
    }
    void ntt(int *a,int type) {
    	for(int i=0;i<=limit;++i)
    		if(i<r[i]) swap(a[i],a[r[i]]);
    	for(int mid=1;mid<limit;mid<<=1) {
    		int Wn=q_pow(3,(mod-1)/(mid<<1));
    		for(int i=0;i<limit;i+=(mid<<1)) {
    			for(int j=0,w=1;j<mid;++j,w=1LL*w*Wn%mod) {
    				int x=a[i+j],y=1LL*w*a[i+j+mid]%mod;
    				a[i+j]=(x+y)%mod;
    				a[i+j+mid]=(x-y+mod)%mod;
    			}
    		}
    	}
    	if(type==-1) {
    		reverse(&a[1],&a[limit]);
    		int inv=q_pow(limit,mod-2);
    		for(int i=0;i<=limit;++i) a[i]=1LL*a[i]*inv%mod;
    	}
    }
    void init() {
    	limit=1,p=0;
    	while(limit<len_b) limit<<=1,p++;
    	for(int i=len_a;i<=limit;++i) a[i]=0;
    	for(int i=len_b;i<=limit;++i) b[i]=0;
    	for(int i=0;i<=limit;++i)
    		r[i]=(r[i>>1]>>1)|((i&1)<<(p-1));
    }
    void solve(int l,int r) {
    	if(l>=r) return;
    	int mid=(l+r)>>1;
    	solve(l,mid);
    	len_a=0,len_b=0;
    	for(int i=l;i<=mid;++i) a[len_a++]=f[i];
    	for(int i=1;i<=r-l;++i) b[len_b++]=g[i];
    	init();
    	ntt(a,1),ntt(b,1);
    	for(int i=0;i<=limit;++i) a[i]=1LL*a[i]*b[i]%mod;
    	ntt(a,-1);
    	for(int i=mid+1;i<=r;++i) f[i]=(f[i]+a[i-l-1])%mod;
    	solve(mid+1,r);
    }
    int main() {
    	n=read();
    	for(int i=1;i<n;++i) g[i]=read();
    	f[0]=1;
    	solve(0,n-1);
    	for(int i=0;i<n;++i) printf("%d ",f[i]);
    	return 0;
    }
    
  • 相关阅读:
    ionic准备之angular基础——dom操作相关(6)
    ionic准备之angular基础——$watch,$apply,$timeout方法(5)
    ionic准备之angular基础——run方法(4)
    ionic准备之angular基础——继承(3)
    开发ionic准备之安卓模拟器设置(2)
    创建你的第一个ionic+cordova应用(1)
    C#nameof用法
    C#中使用goto
    MySQL-解决 Table'performance_schema.session_variables' doesn't exist 问题
    dp方程
  • 原文地址:https://www.cnblogs.com/dsrdsr/p/11207917.html
Copyright © 2011-2022 走看看