[被踩计划] 题解 [省选联考 2020 A 卷] 组合数问题
作者:互联网
为什么叫被踩记录呢?因为感觉自己之前真的是太菜了,打算把之前联赛等考过的题目做一做,看看自已以前有多菜,所以取名叫被踩记录。
题目分析
首先要知道这些东西:
\[n^m=\sum_{i=0}^{n}{n\choose i}{m\brace i}i! \]\[\sum_{i=0}^{n}{n\choose i}x^i=(x+1)^n \]\[{n\choose m}{m\choose k}={n\choose k}{n-k\choose m-k} \]然后就可以愉快地推式子了:
\[\sum_{k=0}^n\sum_{i=0}^ma_ik^ix^k{n\choose k}= \]\[\sum_{k=0}^n\sum_{i=0}^ma_i\sum_{t=0}^i{k\choose t}{i\brace t}t!x^k{n\choose k}= \]\[\sum_{i=0}^ma_i\sum_{t=0}^i{i\brace t}t!\sum_{k=0}^n{k\choose t}{n\choose k}x^k= \]\[\sum_{i=0}^ma_i\sum_{t=0}^i{i\brace t}t!\sum_{k=0}^n{n\choose t}{n-t\choose k-t}x^k= \]\[\sum_{i=0}^ma_i\sum_{t=0}^i{n\choose t}{i\brace t}t!x^t\sum_{k=0}^{n-t}{n-t\choose k}x^k= \]\[\sum_{i=0}^ma_i\sum_{t=0}^i{n\choose t}{i\brace t}t!x^t(x+1)^{n-t} \]预处理 \({n\choose t},{i\brace t},t!,x^t,(x+1)^{n-t}\) ,时间复杂度最多是 \(\mathcal O(m^2\log_2n)\) 的,然后再 \(\mathcal O(m^2)\) 算答案就行了!
参考代码
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define ch() getchar()
#define pc(x) putchar(x)
using namespace std;
template<typename T>void read(T&x){
static char c;static int f;
for(c=ch(),f=1;c<'0'||c>'9';c=ch())if(c=='-')f=-f;
for(x=0;c>='0'&&c<='9';c=ch())x=x*10+(c&15);x*=f;
}
template<typename T>void write(T x){
static char q[65];int cnt=0;
if(x<0)pc('-'),x=-x;
q[++cnt]=x%10,x/=10;
while(x)
q[++cnt]=x%10,x/=10;
while(cnt)pc(q[cnt--]+'0');
}
const int maxm=1005;
int C[maxm],p,S[maxm][maxm],st[maxm],_t[maxm],_x[maxm],_x1[maxm];
int mo(const int x){
return x>=p?x-p:x;
}
int _1;
int power(int a,int x){
int re=_1;
while(x){
if(x&1)re=1ll*re*a%p;
a=1ll*a*a%p,x>>=1;
}
return re;
}
int gcd(int x,int y){
while(y){
int t=x%y;
x=y;
y=t;
}
return x;
}
int main(){
int n,x,m;
read(n),read(x),read(p),read(m);
_1=1%p;S[0][0]=C[0]=_t[0]=_x[0]=_1;
for(int i=1;i<=m;++i){
_t[i]=1ll*_t[i-1]*i%p;
_x[i]=1ll*_x[i-1]*x%p;
st[i]=n-i+1;int cp=i;
for(int j=1;j<=i&&cp>1;++j){
int t=gcd(st[j],cp);
cp/=t,st[j]/=t;
}
C[i]=C[0];
for(int j=1;j<=i;++j)
C[i]=1ll*C[i]*st[j]%p,
S[i][j]=mo(S[i-1][j-1]+1ll*S[i-1][j]*j%p);
}
_x1[m]=power((x+1)%p,n-m);
for(int i=m-1;i>=0;--i)
_x1[i]=1ll*_x1[i+1]*(x+1)%p;
int ans=0;
for(int i=0;i<=m;++i){
int a,te=0;read(a);
for(int t=0;t<=i;++t){
te=mo(te+1ll*C[t]*S[i][t]%p*_t[t]%p*_x[t]%p*_x1[t]%p);
}
ans=mo(ans+1ll*te*a%p);
}
write(ans),pc('\n');
return 0;
}
标签:ma,省选,题解,sum,int,read,choose,brace,联考 来源: https://www.cnblogs.com/lsq147/p/13746426.html