• 【LOJ6067】【2017 山东一轮集训 Day3】第三题 FFT


    【LOJ6067】【2017 山东一轮集训 Day3】第三题 FFT

    题目大意

      给你 (n,b,c,d,e,a_0,a_1,ldots,a_{n-1}),定义

    [egin{align} x_k&=b imes c^{4k}+d imes c^{2k}+e\ f(x)&=sum_{i=0}^{n-1}a_ix^i end{align} ]

      求 (f(x_0),f(x_1),ldots,f(x_{n-1}))

      对 ({10}^6+3) 取模。

    题解

      直接多项式多点求值(显然)会TLE。

      当 (c=0) 时:

    [egin{align} x_k&= egin{cases} b+d+e,&k=0\ e,&k eq 0\ end{cases} end{align} ]

      直接求就好了。

      当 (c eq 0,b=0) 时:

    [egin{align} f(x_k)&=sum_{i=0}^{n-1}a_i{(dc^{2k}+e)}^i\ &=sum_{i=0}^{n-1}a_isum_{j=0}^{i}{(dc^{2k})}^je^{i-j}inom{i}{j}\ &=sum_{j=0}^{n-1}frac{1}{j!}d^jc^{2kj}sum_{i=j}^{n-1}i!a_ie^{i-j}frac{1}{(i-j)!}\ &=sum_{j=0}^{n-1}frac{1}{j!}d^jc^{2kj}sum_{i=0}^{n-j-1}(n-i-1)!a_{n-i-1}e^{(n-i-1)-j}frac{1}{((n-i-1)-j)!}\ &=sum_{j=0}^{n-1}frac{1}{j!}d^jc^{2kj}g_j\ &=sum_{j=0}^{n-1}frac{1}{j!}d^jc^{k^2-({k-j)}^2+j^2}g_j\ &=c^{k^2}sum_{j=0}^{n-1}frac{1}{j!}d^jc^{j^2}g_jfrac{1}{c^{{(k-j)}^2}} end{align} ]

      当 (c eq 0,b eq 0) 时:

    [egin{align} bc^{4k}+dc^{2k}+e&=b(c^{4k}+frac{d}{b}c^{2k})+e\ &=b(c^{4k}+frac{d}{b}c^{2k}+{(frac{d}{2b})}^2-{(frac{d}{2b})}^2)+e\ &=b{(c^{2k}+frac{d}{2b})}^2-frac{d^2}{4b}+e\ &=b{(c^{2k}+d')}^2+e'\ end{align} ]

      然后用 (d')(e') 替换原来的 (d)(e)

    [egin{align} f(x_k)&=sum_{i=0}^{n-1}a_i{(b{(c^{2k}+d)}^2+e)}^i\ &=sum_{i=0}^{n-1}a_isum_{j=0}^{i}b^j{(c^{2k}+d)}^{2j}e^{i-j}inom{i}{j}\ &=sum_{j=0}^{n-1}b^j{(c^{2k}+d)}^{2j}frac{1}{j!}sum_{i=j}^{n-1}a_ii!e^{i-j}frac{1}{i-j}\ &=sum_{j=0}^{n-1}b^j{(c^{2k}+d)}^{2j}frac{1}{j!}g_j\ &=sum_{j=0}^{n-1}b^jfrac{1}{j!}g_jsum_{i=0}^{2j}c^{2ki}d^{2j-i}inom{2j}{i}\ &=sum_{i=0}^{2n-2}c^{2ki}frac{1}{i!}sum_{j=lceilfrac{i}{2} ceil}^{n-1}frac{(2j)!}{j!}b^jg_jfrac{1}{(2j-i)!}d^{2j-i}\ &=sum_{i=0}^{2n-2}c^{2ki}frac{1}{i!}sum_{2jgeq i}^{2n-2}frac{(2j)!}{j!}b^jg_jfrac{1}{(2j-i)!}d^{2j-i}\ &=sum_{i=0}^{2n-2}c^{2ki}frac{1}{i!}h_i\ &=c^{k^2}sum_{i=0}^{2n-2}frac{1}{i!}c^{i^2}h_ifrac{1}{c^{{(i-k)}^2}} end{align} ]

      那些卷积都可以FFT(任意模数FFT)。

      时间复杂度:(O(nlog n))

    代码

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<cstdlib>
    #include<ctime>
    #include<utility>
    #include<functional>
    #include<cmath>
    #include<vector>
    #include<assert.h>
    //using namespace std;
    using std::min;
    using std::max;
    using std::swap;
    using std::sort;
    using std::reverse;
    using std::random_shuffle;
    using std::lower_bound;
    using std::upper_bound;
    using std::unique;
    typedef long long ll;
    typedef unsigned long long ull;
    typedef std::pair<int,int> pii;
    typedef std::pair<ll,ll> pll;
    void open(const char *s){
    #ifndef ONLINE_JUDGE
    	char str[100];sprintf(str,"%s.in",s);freopen(str,"r",stdin);sprintf(str,"%s.out",s);freopen(str,"w",stdout);
    #endif
    }
    int rd(){int s=0,c,b=0;while(((c=getchar())<'0'||c>'9')&&c!='-');if(c=='-'){c=getchar();b=1;}do{s=s*10+c-'0';}while((c=getchar())>='0'&&c<='9');return b?-s:s;}
    void put(int x){if(!x){putchar('0');return;}static int c[20];int t=0;while(x){c[++t]=x%10;x/=10;}while(t)putchar(c[t--]+'0');}
    int upmin(int &a,int b){if(b<a){a=b;return 1;}return 0;}
    int upmax(int &a,int b){if(b>a){a=b;return 1;}return 0;}
    const ll p=1000003;
    const int N=530000;
    ll fp(ll a,ll b)
    {
    	if(!b)
    		return 1;
    	b=(b%(p-1)+p-1)%(p-1);
    	ll s=1;
    	for(;b;b>>=1,a=a*a%p)
    		if(b&1)
    			s=s*a%p;
    	return s;
    }
    namespace fft
    {
    	const int W=524288;
    	const ll M=1000;
    	typedef double db;
    	db pi=acos(-1);
    	struct cp
    	{
    		db x,y;
    		cp(db a=0,db b=0):x(a),y(b){}
    	};
    	cp operator +(cp a,cp b){return cp(a.x+b.x,a.y+b.y);}
    	cp operator -(cp a,cp b){return cp(a.x-b.x,a.y-b.y);}
    	cp operator *(cp a,cp b){return cp(a.x*b.x-a.y*b.y,a.x*b.y+a.y*b.x);}
    	cp operator /(cp a,int b){return cp(a.x/b,a.y/b);}
    	cp conj(cp a){return cp(a.x,-a.y);}
    	cp muli(cp a){return cp(-a.y,a.x);}
    	cp divi(cp a){return cp(a.y,-a.x);}
    	int rev[N];
    	cp *w[20];
    	void fft(cp *a,int n,int t)
    	{
    		for(int i=1;i<n;i++)
    		{
    			rev[i]=(rev[i>>1]>>1)|(i&1?n>>1:0);
    			if(rev[i]>i)
    				swap(a[rev[i]],a[i]);
    		}
    		for(int i=2,s=1;i<=n;i<<=1,s++)
    			for(int j=0;j<n;j+=i)
    				for(int k=0;k<i/2;k++)
    				{
    					cp u=a[j+k];
    					cp v=a[j+k+i/2]*w[s][k];
    					a[j+k]=u+v;
    					a[j+k+i/2]=u-v;
    				}
    		if(t==-1)
    		{
    			reverse(a+1,a+n);
    			for(int i=0;i<n;i++)
    				a[i]=a[i]/n;
    		}
    	}
    	void dft(db *a,db *b,cp *c,cp *d,int n)
    	{
    		static cp a1[N],a2[N];
    		for(int i=0;i<n;i++)
    			a1[i]=cp(a[i],b[i]);
    		fft(a1,n,1);
    		for(int i=0;i<n;i++)
    			a2[i]=conj(a1[i]);
    		reverse(a2+1,a2+n);
    		for(int i=0;i<n;i++)
    		{
    			c[i]=(a1[i]+a2[i])/2;
    			d[i]=divi(a1[i]-a2[i])/2;
    		}
    	}
    	void idft(db *a,db *b,cp *c,cp *d,int n)
    	{
    		static cp a1[N];
    		for(int i=0;i<n;i++)
    			a1[i]=c[i]+muli(d[i]);
    		fft(a1,n,-1);
    		for(int i=0;i<n;i++)
    		{
    			a[i]=a1[i].x;
    			b[i]=a1[i].y;
    		}
    	}
    	void init()
    	{
    		for(int i=1;i<=19;i++)
    			w[i]=new cp[1<<(i-1)];
    		for(int i=0;i<W/2;i++)
    			w[19][i]=cp(cos(2*pi/W*i),sin(2*pi/W*i));
    		for(int i=18;i>=1;i--)
    			for(int j=0;j<1<<(i-1);j++)
    				w[i][j]=w[i+1][j<<1];
    	}
    	void mul(ll *a,ll *b,ll *c,int n,int m,int l)
    	{
    		static db a1[N],a2[N],b1[N],b2[N],c1[N],c2[N],d1[N],d2[N];
    		static cp a3[N],a4[N],b3[N],b4[N],c3[N],c4[N],d3[N],d4[N];
    		int k=1;
    		while(k<=n+m)
    			k<<=1;
    		for(int i=0;i<k;i++)
    			a1[i]=a2[i]=b1[i]=b2[i]=0;
    		for(int i=0;i<=n;i++)
    		{
    			a[i]=(a[i]+p)%p;
    			a1[i]=a[i]/M;
    			a2[i]=a[i]%M;
    		}
    		for(int i=0;i<=m;i++)
    		{
    			b[i]=(b[i]+p)%p;
    			b1[i]=b[i]/M;
    			b2[i]=b[i]%M;
    		}
    		dft(a1,a2,a3,a4,k);
    		dft(b1,b2,b3,b4,k);
    		for(int i=0;i<k;i++)
    		{
    			c3[i]=a3[i]*b3[i];
    			c4[i]=a3[i]*b4[i];
    			d3[i]=a4[i]*b3[i];
    			d4[i]=a4[i]*b4[i];
    		}
    		idft(c1,c2,c3,c4,k);
    		idft(d1,d2,d3,d4,k);
    		for(int i=0;i<=l;i++)
    			c[i]=((ll)(c1[i]+0.5)%p*M%p*M%p+(ll)(c2[i]+0.5)%p*M%p+(ll)(d1[i]+0.5)%p*M%p+(ll)(d2[i]+0.5)%p)%p;
    	}
    }
    int n;
    ll B,C,D,E;
    ll a[N];
    ll inv[N],fac[N],ifac[N];
    void init()
    {
    	inv[1]=fac[0]=fac[1]=ifac[0]=ifac[1]=1;
    	for(int i=2;i<=200000;i++)
    	{
    		inv[i]=-p/i*inv[p%i]%p;
    		inv[i]=(inv[i]+p)%p;
    		fac[i]=fac[i-1]*i%p;
    		ifac[i]=ifac[i-1]*inv[i]%p;
    	}
    }
    namespace pregao
    {
    	ll b[N],c[N],s[N];
    	void gao()
    	{
    		for(int i=0;i<n;i++)
    		{
    			b[i]=a[n-i-1]*fac[n-i-1]%p;
    			c[i]=ifac[i]*fp(E,i)%p;
    		}
    		fft::mul(b,c,s,n-1,n-1,n-1);
    		reverse(s,s+n);
    	}
    }
    namespace gao1
    {
    	ll d[N],e[N],f[N],g[N],h[N],ans[N];
    	void gao()
    	{
    		pregao::gao();
    		for(int i=0;i<n;i++)
    		{
    			d[i]=pregao::s[i]*fp(D,i)%p*fp(C,(ll)i*i)%p*ifac[i]%p;
    			e[i]=fp(C,-(ll)i*i);
    		}
    		fft::mul(d,e,f,n-1,n-1,n-1);
    		reverse(d,d+n);
    		e[0]=0;
    		fft::mul(d,e,g,n-1,n-1,n-1);
    		for(int i=0;i<n;i++)
    		{
    			ans[i]=((f[i]+g[n-i-1])%p+p)%p;
    			ans[i]=ans[i]*fp(C,(ll)i*i)%p;
    		}
    		for(int i=0;i<n;i++)
    			printf("%lld
    ",ans[i]);
    	}
    }
    namespace gao2
    {
    	ll b[N],c[N],d[N],e[N],f[N],g[N],ans[N];
    	void gao()
    	{
    		E=(E-D*D%p*fp(4*B,p-2)%p+p)%p;
    		D=D*fp(2*B,p-2)%p;
    		pregao::gao();
    		for(int i=0;i<n;i++)
    			b[2*n-2*i-2]=fac[2*i]*ifac[i]%p*pregao::s[i]%p*fp(B,i)%p;
    		for(int i=0;i<2*n-1;i++)
    			c[i]=fp(D,i)*ifac[i]%p;
    		fft::mul(b,c,d,2*n-2,2*n-2,2*n-2);
    		reverse(d,d+2*n-1);
    		for(int i=0;i<2*n-1;i++)
    		{
    			d[i]=d[i]*ifac[i]%p*fp(C,(ll)i*i)%p;
    			e[i]=fp(C,-(ll)i*i);
    		}
    		fft::mul(d,e,f,n-1,n-1,n-1);
    		reverse(d,d+2*n-1);
    		e[0]=0;
    		fft::mul(d,e,g,2*n-2,2*n-2,2*n-2);
    		for(int i=0;i<n;i++)
    			ans[i]=(fp(C,(ll)i*i)*(f[i]+g[2*n-i-2])%p+p)%p;
    		for(int i=0;i<n;i++)
    			printf("%lld
    ",ans[i]);
    	}
    }
    namespace gao0
    {
    	void gao()
    	{
    		ll ans=0;
    		for(int i=n-1;i>=0;i--)
    		{
    			ans=ans*(E+B+D)%p;
    			ans=(ans+a[i])%p;
    		}
    		printf("%lld
    ",ans);
    		ans=0;
    		for(int i=n-1;i>=0;i--)
    		{
    			ans=ans*E%p;
    			ans=(ans+a[i])%p;
    		}
    		for(int i=1;i<n;i++)
    			printf("%lld
    ",ans);
    	}
    }
    int main()
    {
    	open("loj6067");
    	fft::init();
    	init();
    	scanf("%d%lld%lld%lld%lld",&n,&B,&C,&D,&E);
    	for(int i=0;i<n;i++)
    		a[i]=rd();
    	if(!C)
    		gao0::gao();
    	else if(!B)
    		gao1::gao();
    	else
    		gao2::gao();
    	return 0;
    }
    
  • 相关阅读:
    23种设计模式-原型模式
    23种设计模式-工厂方法模式
    23种设计模式-代理模式
    23种设计模式-装饰模式
    23种设计模式-策略模式
    CSS高度塌陷问题与解决办法
    Java: 多态
    Java: 接口
    Java: 继承
    Java: 单例设计模式
  • 原文地址:https://www.cnblogs.com/ywwyww/p/9220869.html
Copyright © 2020-2023  润新知