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;
    }
    
  • 相关阅读:
    What's the difference between tilde(~) and caret(^) in package.json?
    腾迅股票数据接口
    dddd
    https://wrapbootstrap.com
    http://tpl.amazeui.org/
    http://www.ajaxload.info/
    基于Sublime Text搭建Python IDE
    IDAPython: importing “site” failed
    IDA_Python命令行使用
    “error LNK2019: 无法解析的外部符号”之分析
  • 原文地址:https://www.cnblogs.com/jz-597/p/14766229.html
Copyright © 2011-2022 走看看