zoukankan      html  css  js  c++  java
  • 模拟赛 斯特林数计数 题解(拉格朗日插值)

    题目大意:

    答案对(10^9 + 7)取模。

    首先,我们发现这个东西出现了很多次。
    设R=

    R可以矩阵乘法求。
    根据斯特林数的

    原式可化为
    设所求为(f_k(N))

    对于(R=1)的情况,自然数幂求和即可。(O(k+logn))

    所以,

    由上述暴力展开的情况可以发现,存在一个关于(N)(m)多项式(F_m(N))
    使得(f_m(N)=F_m(N)R^{N+1}-F_m(0)R),利用上述的展开方式也可归纳证明这个结论。

    所以,求出(F_m(N))即可,由于它是(m)次多项式,所以,求出(F_m(0)到F_m(m))即可插值求出(F_m(N))
    因为(f_m(N)-f_m(N-1)=F_m(N)R^{N+1}-F_m(N-1)R^N=N^m R^N),所以(F_m(N)R-F_m(N-1)=N^m)
    (F_m(N)=frac{N^m+F_m(N-1)}{R})
    (F_m(0)=x),那么(F_m(i))就能表示为(k_ix+b_i)的形式。
    那么,我们只要再找一条(F_m)的等量关系即可求出。

    代入到上一条式子,即可得出

    (其实就是说m次多项式的m+1次差分等于0,这条式子可以保证(F_m)形成一个m次多项式)。
    也可以这样理解:我们用(m+1)个点(0~m)就能确定一个多项式,但要保证确定的多项式代入(m+1)的值是正确的。
    通过拉格朗日插值也能得出这条式子。

    这样,我们就能求出(F_m(0)到F_m(m)),再通过插值,即可求出(F_m(N)),进而求出答案。

    通过线性筛,可以在计算质数(p)(p^m)后线性地算出所有正整数(x)(x^m)
    时间复杂度为(O(frac{m}{ln(m)}*log_2(m))=O(m))

    总时间复杂度(O(k+logn))

    代码:

    #include <stdio.h>
    #define md 1000000007
    #define ll long long
    int ny[200010],jc[200010],jn[200010];
    int C(int n,int m)
    {
    	return 1ll*jc[n]*jn[m]%md*jn[n-m]%md;
    }
    int ksm(int a,int b)
    {
    	int jg=1;
    	while(b>0)
    	{
    		if(b&1)
    			jg=1ll*jg*a%md;
    		a=1ll*a*a%md;
    		b=(b>>1);
    	}
    	return jg;
    }
    int getfib(ll x)
    {
    	int a=1,b=0,c=0,d=1,w[70],s=0;
    	while(x>0)
    	{
    		w[s++]=x%2;
    		x/=2;
    	}
    	for(int i=s-1;i>=0;i--)
    	{
    		int bc=1ll*b*c%md,ad=(a+d)%md;
    		b=1ll*b*ad%md;c=1ll*c*ad%md;
    		a=(1ll*a*a+bc)%md;
    		d=(1ll*d*d+bc)%md;
    		if(w[i])
    		{
    			int ta=a,tc=c;
    			a=(a+b)%md;
    			c=(c+d)%md;
    			b=ta;d=tc;
    		}
    	}
    	return c;
    }
    int qz[200010],hz[200010];
    int jisuan(int sz[200010],int n,ll x)
    {
    	for(int i=0;i<=n;i++)
    	{
    		if(i==0)qz[i]=1;
    		else qz[i]=qz[i-1];
    		qz[i]=1ll*qz[i]*(x%md-i+md)%md;
    	}
    	for(int i=n;i>=0;i--)
    	{
    		if(i==n)hz[i]=1;
    		else hz[i]=hz[i+1];
    		hz[i]=1ll*hz[i]*(x%md-i+md)%md;
    	}
    	int ans=0;
    	for(int i=0;i<=n;i++)
    	{
    		int l=1ll*jn[i]*jn[n-i]%md;
    		if(i>0)l=1ll*l*qz[i-1]%md;
    		if(i<n)l=1ll*l*hz[i+1]%md;
    		if((n-i)%2==1)
    			l=1ll*l*(md-1)%md;
    		ans=(ans+1ll*l*sz[i])%md;
    	}
    	return ans;
    }
    int mi[200010],k[200010],b[200010],S[200010],F[200010];
    int sa[200010],ss[200010],sl=0;
    void yucl(int x,int m)
    {
    	mi[1]=1;
    	for(int i=2;i<=x;i++)
    	{
    		if(!sa[i])
    		{
    			ss[sl++]=i;
    			mi[i]=ksm(i,m);
    		}
    		for(int j=0;j<sl;j++)
    		{
    			if(1ll*i*ss[j]>x)
    				break;
    			sa[i*ss[j]]=true;
    			mi[i*ss[j]]=1ll*mi[i]*mi[ss[j]]%md;
    			if(i%ss[j]==0)break;
    		}
    	}
    }
    int main()
    {
    	freopen("c.in","r",stdin);
    	freopen("c.out","w",stdout);
    	ll n,r;int K;
    	scanf("%lld%lld%d",&n,&r,&K);
    	ny[1]=jc[0]=jn[0]=1;
    	for(int i=2;i<=K+1;i++)
    		ny[i]=1ll*(md-md/i)*ny[md%i]%md;
    	for(int i=1;i<=K+1;i++)
    	{
    		jc[i]=1ll*jc[i-1]*i%md;
    		jn[i]=1ll*jn[i-1]*ny[i]%md;
    	}
    	yucl(K+1,K);
    	int R=(getfib(r+2)-1+md)%md;
    	if(R==1)
    	{
    		for(int i=1;i<=K+1;i++)
    			mi[i]=(mi[i]+mi[i-1])%md;
    		printf("%d",jisuan(mi,K+1,n));
    	}
    	else
    	{
    		int rn=ksm(R,md-2);
    		k[0]=1;b[0]=0;
    		for(int i=1;i<=K+1;i++)
    		{
    			k[i]=1ll*k[i-1]*rn%md;
    			b[i]=1ll*(b[i-1]+mi[i])*rn%md;
    		}
    		int hk=0,hb=0;
    		for(int i=0;i<=K+1;i++)
    		{
    			int t=C(K+1,i);
    			if(i%2==1)
    				t=1ll*t*(md-1)%md;
    			hk=(hk+1ll*t*k[i])%md;
    			hb=(hb+1ll*t*b[i])%md;
    		}
    		F[0]=1ll*(md-hb)*ksm(hk,md-2)%md;
    		for(int i=1;i<=K;i++)
    			F[i]=(1ll*k[i]*F[0]+b[i])%md;
    		int fn=jisuan(F,K,n);
    		int ans=1ll*fn*ksm(R,(n+1)%(md-1))%md;
    		ans=(ans-1ll*F[0]*R%md+md)%md;
    		printf("%d
    ",ans);
    	}
    	fclose(stdin);
    	fclose(stdout);
    	return 0;
    }
    
  • 相关阅读:
    判断两个数组是否相等
    正则表达式的正向预查
    IFC布局特点
    XSS攻击总结
    String与toString
    link与@import
    BFC布局
    单例模式
    <input type="radio" >与<input type="checkbox">值得获取
    Struts标签<s:iterator>遍历访问复杂Map对象
  • 原文地址:https://www.cnblogs.com/lnzwz/p/11618013.html
Copyright © 2011-2022 走看看