zoukankan      html  css  js  c++  java
  • 51nod 1172 Partial Sums V2

    题目

    给出一个数组A,经过一次处理,生成一个数组S,数组S中的每个值相当于数组A的累加,比如:A = {1 3 5 6} => S = {1 4 9 15}。如果对生成的数组S再进行一次累加操作,{1 4 9 15} => {1 5 14 29},现在给出数组A,问进行K次操作后的结果。(输出结果 Mod 10^9 + 7)

    分析

    发现,每次处理相当于将A卷上一个(I(forall a_i=1))
    于是机智的我在wiki又发现狄利克雷卷积满足交换律(我居然才知道)
    于是快速幂咯,时间复杂度(O(nlog^2n)),常数巨大,在51nod的老爷机上根本过不了。
    然后就TLE得一塌糊涂。
    于是找规律,发现(ans_k=sum_{i+j=k}A_iC_{j+n-1}^{j})
    然后NTT
    但是,(10^9+7)并没有原根,所以祭出三模数NTT(如果有人想用高精度,我也没办法)。
    因为((10^9+7)^2*napprox10^{23}),所以找三个(10^9)左右的模数。
    假设

    [ans≡a_0(mod m_0) ]

    [ans≡a_1(mod m_1) ]

    [ans≡a_2(mod m_2) ]

    因为(m_0m_1m_2)会爆long long
    所有,通过CRT(中国剩余定理)合并前两项,于是(M=m_0*m_1)

    [ans≡A(mod M) ]

    [ans≡a_2(mod m_2) ]

    (ans=kM+A)
    因为$$kM+A≡ans≡a_2(mod m_2)$$
    所以$$k≡(a_2-A)M^{-1}(mod m_2)$$
    那么根据上面的式子求出k,通过(kM+A=ans)就可以求出ans了。

    #include <cmath>
    #include <iostream>
    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <algorithm>
    #include <queue>
    #include <map>
    #include <bitset>
    #include <set>
    const int maxlongint=2147483647;
    const long long mo=1e9+7;
    const int N=200005;
    using namespace std;
    long long mod[3]={469762049,998244353,1004535809},M=mod[0]*mod[1],W[3][N];
    long long f[3][N],g[3][N],v[3][N],v_[N],jc[3][N],ny[3][N],inv[N];
    int n,m,fn;
    long long poww(long long x,long long y,int z)
    {
    	long long s=1;
    	x%=mod[z];
    	for(;y;x=x*x%mod[z],y>>=1)
    		if(y&1) s=s*x%mod[z];
    	return s;
    }
    long long mul(long long x,long long y,long long mo)
    {
    	long long s=0;
    	x%=mo;
    	for(;y;x=(x+x)%mo,y>>=1)
    		if(y&1) s=(s+x)%mo;
    	return s;
    }
    void NTT(long long *f,int type,int z)
    {
    	for(int i=0,p=0;i<fn;i++)
    	{
    		if(i<p) swap(f[i],f[p]);
    		for(int j=fn>>1;(p^=j)<j;j>>=1);
    	}
    	for(int i=2;i<=fn;i<<=1)
    	{
    		int half=i>>1,pe=fn/i;
    		for(int j=0;j<half;j++)
    		{
    			long long w=!type?W[z][j*pe]:W[z][fn-j*pe];
    			for(int k=j;k<fn;k+=i)
    			{
    				long long x=f[k],y=f[k+half]*w%mod[z];
    				f[k]=(x+y)%mod[z],f[k+half]=(x-y+mod[z])%mod[z];
    			}
    		}
    	}
    	if(type)
    	{
    		long long ni=poww(fn,mod[z]-2,z);
    		for(int i=0;i<fn;i++) f[i]=f[i]*ni%mod[z];
    	}
    }
    long long CRT(long long a0,long long a1,long long a2)
    {
    	long long n0=poww(mod[1],mod[0]-2,0),n1=poww(mod[0],mod[1]-2,1);
    	long long A=(mul(a0*mod[1]%M,n0%M,M)+mul(a1*mod[0]%M,n1%M,M))%M,n2=poww(M%mod[2],mod[2]-2,2);
    	long long k=(a2-A)%mod[2]*n2%mod[2];
    	k=(k%mod[2]+mod[2])%mod[2];
    	return (k%mo*(M%mo)%mo+A)%mo;
    }
    int main()
    {
    	scanf("%d%d",&n,&m);
    	for(fn=1;fn<=n*2+2;fn<<=1);
    	inv[0]=inv[1]=1;
    	for(int i=2;i<=fn;i++) inv[i]=(-(mo/i)*inv[mo%i]%mo+mo)%mo;
    	for(int i=0;i<n;i++) scanf("%lld",&f[0][i]),f[1][i]=f[2][i]=f[0][i];
    	for(int j=0;j<3;j++)
    	{
    		W[j][0]=1,W[j][1]=poww(3,(mod[j]-1)/fn,j);
    		for(int i=2;i<=fn;i++) W[j][i]=W[j][i-1]*W[j][1]%mod[j];
    		for(int i=0;i<n;i++) v[j][i]=1;
    		g[j][0]=1;
    		for(int i=1;i<n;i++) g[j][i]=g[j][i-1]*(i+m-1)%mo*inv[i]%mo;
    	}
    	for(int j=0;j<3;j++)
    	{
    		NTT(f[j],0,j),NTT(g[j],0,j);
    		for(int i=0;i<fn;i++) f[j][i]=f[j][i]*g[j][i]%mod[j];
    		NTT(f[j],1,j);
    	}
    	for(int i=0;i<n;i++) printf("%lld
    ",CRT(f[0][i],f[1][i],f[2][i]));
    }
    
  • 相关阅读:
    Algebra, Topology, Differential Calculus, and Optimization Theory For Computer Science and Machine Learning 第4章 读书笔记(待更新)
    Algebra, Topology, Differential Calculus, and Optimization Theory For Computer Science and Machine Learning 第3章 读书笔记(待更新)
    Algebra, Topology, Differential Calculus, and Optimization Theory For Computer Science and Machine Learning 第1,2章 读书笔记(待更新)
    Tkinter的Message组件
    Git 实操/配置/实践
    mysq5.7.32-win安装步骤
    行为型模式之模板方法
    结构型模式之组合模式
    结构型模式之享元模式
    结构型模式之外观模式
  • 原文地址:https://www.cnblogs.com/chen1352/p/9099498.html
Copyright © 2011-2022 走看看