• P6620[省选联考2020A卷]组合数问题【组合数学,斯特林数】


    正题

    题目链接:https://www.luogu.com.cn/problem/P6620


    题目大意

    给出\(n,x,p,m\)和一个\(m\)次多项式\(f\)

    \[\sum_{k=0}^nf(k)\times x^k\times \binom{n}{k} \]

    答案对\(p\)取模。

    \(1\leq n\leq 10^9,1\leq m\leq 1000\)


    解题思路

    什么混凝土数学题

    首先我们发现这个组合数\(\binom{n}{k}\)处理的十分难受,有一个下降幂的结论正好可以把这个难受的\(k\)变掉。

    \[\binom{n}{k}\times k^{\underline{m}}=\binom{n-m}{k-m}\times n^{\underline m} \]

    我们需要找到一个东西来提供\(k^{\underline m}\),此时给我们的多项式\(f\)就是一个不错的选择。

    我们考虑把多项式转换为下降幂的形式

    \[f(x)=\sum_{i=0}^ma_ix^i=\sum_{i=0}^mb_ix^{\underline i} \]

    考虑一下怎么找到序列\(b_i\),也就是我们需要把\(x^i\)转换为下降幂的形式,有一个第二类斯特林数的性质就是

    \[x^n=\sum_{i=0}^{n}{\begin{Bmatrix}n\\i\end{Bmatrix}}x^{\underline i} \]

    \[\sum_{i=0}^ma_ix^i=\sum_{i=0}^ma_i\sum_{j=0}^i{\begin{Bmatrix}i\\j\end{Bmatrix}}x^{\underline j}\Rightarrow b_i=\sum_{i=j}^n{\begin{Bmatrix}j\\i\end{Bmatrix}}x^{\underline{i}} \]

    然后就可以继续推我们的式子了

    \[\sum_{k=0}^n\sum_{i=0}^mb_ik^{\underline i}\times x^k\times \binom{n}{k} \]

    \[\sum_{k=0}^n\sum_{i=0}^mb_ix^k\binom{n-i}{k-i}n^{\underline i} \]

    \(i\)提出去枚举

    \[\sum_{i=0}^mb_in^{\underline i}\sum_{k=0}^nx^k\binom{n-i}{k-i} \]

    \[\Rightarrow \sum_{i=0}^mb_in^{\underline i}x^i\sum_{k=0}^{n-i}\binom{n-i}{k}x^k \]

    然后后面那个式子就可以二项式定理了

    \[\Rightarrow \sum_{i=0}^mb_in^{\underline i}x^i(x+1)^{n-i} \]

    然后就搞定了

    时间复杂度\(O(m^2+m\log n)\)


    code

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #define ll long long
    using namespace std;
    const ll N=1100;
    ll n,x,m,P,a[N],b[N],s[N][N],ans;
    ll power(ll x,ll b){
    	ll ans=1;
    	while(b){
    		if(b&1)ans=ans*x%P;
    		x=x*x%P;b>>=1;
    	}
    	return ans;
    }
    signed main()
    {
    	scanf("%lld%lld%lld%lld",&n,&x,&P,&m);
    	for(ll i=0;i<=m;i++)scanf("%lld",&a[i]);
    	s[0][0]=1; 
    	for(ll i=1;i<=m;i++)
    		for(ll j=1;j<=i;j++)
    			s[i][j]=(s[i-1][j]*j%P+s[i-1][j-1])%P;
    	for(ll i=0;i<=m;i++)
    		for(ll j=i;j<=m;j++)
    			(b[i]+=a[j]*s[j][i]%P)%=P;
    	for(ll i=0,tmp=1;i<=m;i++){
    		(ans+=b[i]*tmp%P*power(x,i)%P*power(x+1,n-i)%P)%=P;
    		tmp=tmp*(n-i)%P;
    	}
    	printf("%lld\n",ans);
    	return 0;
    }
    
  • 相关阅读:
    Android的Activity屏幕切换动画(一)-左右滑动切换
    404 Not Found 由来
    HTML+CSS 制作HTML5标志图
    发现 网站错误
    链接指南
    偷懒省事有工具啊
    程序员很穷(转)
    谷歌浏览器修改CSS和js后同步保存到文件中 (译)
    程序员眼睛的保护(爱护眼睛,你我做起)
    仿站违法和侵权吗?
  • 原文地址:https://www.cnblogs.com/QuantAsk/p/14578690.html
Copyright © 2020-2023  润新知