zoukankan      html  css  js  c++  java
  • ARC118F Growth Rate

    给出个长度为(n)的序列(A_i),问有多少个长度为(n+1)的序列(X_i),满足:

    1. (X_iin [1,m])
    2. (A_iX_ile X_{i+1})

    (nle 1000,mle 10^{18},prod A_ile M)


    首先有个暴力:从后往前做,设(f_k(x))表示第(k)位选择(x)的方案数是什么。

    转移:(f_k(x)=sum_{yge ax} f_{k+1}(y))

    结论:(f_k(x))是个关于(x)的多项式,定义域为([1,R])(R)为原题意中于(k)位置能合法放置的最大数。原因根据以下做法,归纳就能说明。

    假设已经知道了(f_k(y)=sum_i a_i y^i)

    (F_k(x))表示(f_k(x))的前缀和,即(F_{k}(x)=sum_{yle x} f_k(y)=sum_i a_i sum_{yle x}y^i),后面是个自然数幂和,所以(F_k(x))也是多项式。

    根据转移,(f_{k+1}(x)=F_k(R)-F_k(ax-1))。显然(f_{k+1}(x))也是多项式。

    现在问题是两个:给多项式做前缀和;给多项式复合(ax-1)

    先讲题解做法:

    考虑维护若干个点值(假设(c)个,(c=O(n))),分别为(1,2,dots c)

    前缀和:直接用点值前缀和。时间(O(n))

    复合:对于每个点(x_i),通过拉格朗日插值查(F_k(ax_i-1))。时间(O(n^2))

    (A_k>1)时直接(O(n^2))复合,次数(O(lg m))次;(A_k=1)时特殊处理:前缀和就直接前缀和,后面是(F_k(R)-F_k(x-1))(F_k(x-1))已知可以直接用。于是时间(O(n))

    于是总时间(O(n^2lg m))

    我的口胡做法:

    考虑对前缀和进行一波多项式推导(以下(B)为伯努利数(B^+)):

    [sum_i a_i sum_{yle x}y^i\ =sum_i a_i frac{1}{i+1}sum_{j=1}^{i+1}inom{i+1}{j}B_{i+1-j}x^{j}\ =sum_{jge 1}x^{j}sum_{i+1ge j}a_i frac{1}{i+1}inom{i+1}{j}B_{i+1-j}\ =sum_{jge 1}frac{x^{j}}{j!}sum_{i+1ge j}(a_ii!) frac{B_{i+1-j}}{(i+1-j)!}\ ]

    可以发现最后是个减法卷积的形式。

    再对复合进行一波多项式推导:

    [F(ax-1)\ =sum_i F_i(ax-1)^i\ =sum_i F_isum_{j=0}^ia^jx^j(-1)^{i-j}inom{i}{j}\ =sum_{j}a^jx^j(-1)^{j}sum_{ige j} F_iinom{i}{j}(-1)^i\ =sum_{j}a^jx^jfrac{(-1)^{j}}{j!}sum_{ige j} left(F_ii!(-1)^i ight)left(frac{1}{(i-j)!} ight) ]

    也是个减法卷积的形式。

    于是全程用多项式做,可以搞到(O(n^2 lg n))的复杂度。


    using namespace std;
    #include <bits/stdc++.h>
    #define N 1005
    #define ll long long
    #define mo 998244353
    ll qpow(ll x,ll y=mo-2){
    	ll r=1;
    	for (;y;y>>=1,x=x*x%mo)
    		if (y&1)
    			r=r*x%mo;
    	return r;
    }
    int n,k;
    ll m,a[N];
    ll d[N],R;
    ll fac[N],ifac[N];
    void initC(int n){
    	fac[0]=1;
    	for (int i=1;i<=n;++i)
    		fac[i]=fac[i-1]*i%mo;
    	ifac[n]=qpow(fac[n]);
    	for (int i=n-1;i>=0;--i)
    		ifac[i]=ifac[i+1]*(i+1)%mo;
    }
    ll ask(ll z){
    	if (z>R || z<1) return 0;
    	z%=mo;
    	ll y=0,pre=1;
    	static ll suc[N];
    	suc[k+1]=1;
    	for (int x=k;x>=1;--x)
    		suc[x]=suc[x+1]*(z-x)%mo;
    	for (int x=1;x<=k;++x){
    		ll tmp=pre*suc[x+1]%mo;
    		(y+=d[x]*tmp%mo*ifac[k-x]%mo*ifac[x-1]*(k-x&1?-1:1))%=mo;
    		pre=pre*(z-x)%mo;
    	}
    	return (y+mo)%mo;
    }
    ll C(ll m,ll n){
    	ll s=1;
    	for (ll i=m-n+1;i<=m;++i)
    		s=s*i%mo;
    	for (ll i=1;i<=n;++i)
    		s=s*qpow(i)%mo;
    	return s;
    }
    int main(){
    	//freopen("in.txt","r",stdin);
    	scanf("%d%lld",&n,&m);
    	for (int i=1;i<=n;++i)
    		scanf("%lld",&a[i]);
    	k=n+2;
    	initC(k);
    	R=m;
    	for (int x=1;x<=k;++x)
    		d[x]=min((ll)x,m);
    	m%=mo;
    	for (int i=n;i>=1;--i){
    		ll sum=ask(R);
    		if (a[i]==1){
    			for (int x=k;x>=1;--x)
    				d[x]=(sum-d[x-1]+mo)%mo;
    		}
    		else{
    			static ll t[N];
    			for (int x=k;x>=1;--x)
    				t[x]=(sum-ask(a[i]*x-1)+mo)%mo;
    			memcpy(d,t,sizeof(ll)*(k+1));			
    		}
    		R=R/a[i];
    		for (int x=1;x<=k;++x)
    			d[x]=(d[x]+d[x-1]+mo)%mo;
    	}
    	ll ans=ask(R);
    	printf("%lld
    ",ans);
    	return 0;
    }
    
  • 相关阅读:
    How to alter department in PMS system
    Can't create new folder in windows7
    calculate fraction by oracle
    Long Wei information technology development Limited by Share Ltd interview summary.
    ORACLE BACKUP AND RECOVERY
    DESCRIBE:When you mouse click right-side is open an application and click left-side is attribution.
    ORACLE_TO_CHAR Function
    电脑BOIS设置
    JSP点击表头排序
    jsp+js实现可排序表格
  • 原文地址:https://www.cnblogs.com/jz-597/p/14766229.html
Copyright © 2011-2022 走看看