• [被踩计划] 题解 [省选联考 2020 A 卷] 组合数问题


    为什么叫被踩记录呢?因为感觉自己之前真的是太菜了,打算把之前联赛等考过的题目做一做,看看自已以前有多菜,所以取名叫被踩记录。

    题目链接

    题目分析

    首先要知道这些东西:

    [n^m=sum_{i=0}^{n}{nchoose i}{mrace i}i! ]

    [sum_{i=0}^{n}{nchoose i}x^i=(x+1)^n ]

    [{nchoose m}{mchoose k}={nchoose k}{n-kchoose m-k} ]

    然后就可以愉快地推式子了:

    [sum_{k=0}^nsum_{i=0}^ma_ik^ix^k{nchoose k}= ]

    [sum_{k=0}^nsum_{i=0}^ma_isum_{t=0}^i{kchoose t}{irace t}t!x^k{nchoose k}= ]

    [sum_{i=0}^ma_isum_{t=0}^i{irace t}t!sum_{k=0}^n{kchoose t}{nchoose k}x^k= ]

    [sum_{i=0}^ma_isum_{t=0}^i{irace t}t!sum_{k=0}^n{nchoose t}{n-tchoose k-t}x^k= ]

    [sum_{i=0}^ma_isum_{t=0}^i{nchoose t}{irace t}t!x^tsum_{k=0}^{n-t}{n-tchoose k}x^k= ]

    [sum_{i=0}^ma_isum_{t=0}^i{nchoose t}{irace t}t!x^t(x+1)^{n-t} ]

    预处理 ({nchoose t},{irace t},t!,x^t,(x+1)^{n-t}) ,时间复杂度最多是 (mathcal O(m^2log_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('
    ');
    	return 0;
    }
    
    
  • 相关阅读:
    HelloWorld入门程序
    list的几种遍历方式
    遍历map的几种方法
    Java动态代理
    七月七日学习记录
    七月六日学习报告
    钢镚儿使用体验
    TD tree 使用体验
    学习笔记154—Matlab 如何写入txt?
    学习笔记153—matlab中小数如何取整?
  • 原文地址:https://www.cnblogs.com/lsq147/p/13746426.html
Copyright © 2020-2023  润新知