zoukankan      html  css  js  c++  java
  • [省选联考 2020 A 卷] 组合数问题 题解报告

    题目要求

    [sum_{k=0}^nf(k) imes x^k imesdbinom{n}{k} ]

    我觉得 ix35 的方法还是蛮不错的,其他的斯特林数推导和组合意义 dp 都给我看傻了

    首先考虑将 (f) 拆成单项式有

    [sum_{i=0}^ma_i imes k^i imes dbinom{n}{k} ]

    (k imes dbinom{n}{k}=n imes dbinom{n-1}{k-1}) 向外扩展

    (k^2 imes dbinom{n}{k},k^3 imesdbinom{n}{k}dots) 手算一遍

    可以发现对于 (k^p imes dbinom{n}{k}) 有一般形式

    [=sum_{i=1}^pS(p,j) imes n^{underline{j}} imesdbinom{n-j}{k-j} ]

    并且对于 (S(p,j)=S(i-1,j) imes j+S(i-1,j-1)) 存在这个递归式

    这个时候回带到原式中

    [sum_{k=0}^{n}x^kleft(a_0+sum_{i=1}^ma_i imes k^i imes dbinom{n}{k} ight) ]

    务必要特殊讨论 (a_0) 的存在,否则你会因为这个死活过不去大样例。

    把关于 n 的求和符号换进去,可以得到这样一个式子

    [sum_{k=0}^nx^ksum_{j=1}^i S(i,j) imes n^{underline{j}} imesdbinom{n-j}{k-j} ]

    进一步交换

    [sum_{j=1}^i S(i,j) imes n^{underline{j}} imessum_{k=0}^nx^kdbinom{n-j}{k-j} ]

    单独考虑后面那个求和符号,等价于

    [x^jsum_{k=0}^{n-j}xdbinom{n-j}{k} ]

    再用一步二项式定理(一定要带着那个 (x^j),不然还是只能过第一个样例

    [x^j imes(1+x)^{n-j} ]

    整理一下

    [a_0(1+x)^n+sum_{i=1}^ma_ileft(sum_{j=1}^iS(i,j) imes n^{underline{j}} imes x^j imes(1+x)^{n-j} ight) ]

    然后这个一个依赖 (n) 的算法被我们改造成了依赖 (m) 的算法,复杂度是 (O(m^2log m))

    #include<bits/stdc++.h>
    
    using namespace std;
    
    #define int long long
    #define pii pair<int,int>
    
    template<typename _T>
    inline void read(_T &x)
    {
    	x=0;char s=getchar();int f=1;
    	while(s<'0'||s>'9') {f=1;if(s=='-')f=-1;s=getchar();}
    	while('0'<=s&&s<='9'){x=(x<<3)+(x<<1)+s-'0';s=getchar();}
    	x*=f;
    }
    
    const int np = 1e3 + 5;
    
    int a[np];
    int x,n,m,p;
    int s[np][np];
    int dfac[np];
    int x_[np];
    
    inline int power(int a,int b)
    {
    	int res(1);
    	while(b)
    	{
    		if(b & 1) res = res * a,res %= p;
    		a = a * a ;
    		a %= p;
    		b >>= 1;
    	}
    	return res;
    }
    
    signed main()
    {
    	read(n),read(x),read(p),read(m);
    	for(int i=0;i <=m;i++) read(a[i]);
    	for(int i=1;i <= 1000;i ++)
    	{
    		s[i][1] = 1;
    		for(int j=2;j <= i;j++)
    		{
    			s[i][j] = s[i-1][j]*j+s[i-1][j-1];
    			s[i][j] %= p;
    		}
    		// for(int j=1;j<=i;j++) printf("%lld ",s[i][j]);
    		// printf("
    ");		
    	}
    
    	dfac[0] =1 ;
    	for(int i=1;i <= 1000;i ++)
    	{
    		dfac[i] = dfac[i-1]*(n-i+1);
    		dfac[i] %= p;
    	}
    
    	int Ans =power(1+x,n)*a[0];
    	Ans %= p;
    	for(int i=1;i <= m;i ++)
    	{
    		int qAns = 0;
    		for(int j=1;j <= i;j ++)
    		{
    			qAns += ((((s[i][j] * dfac[j])%p) * power(x,j)%p) *power(1 + x,n-j))%p;
    			qAns %= p;
    		}
    		qAns *= a[i];
    		qAns %= p;
    		Ans += qAns;
    		Ans %= p;
    		// printf("%lld
    ",Ans);
    	}
    
    	// Ans  += ((n+1) * n* a[0])%p;
    	// Ans %= p;
    	printf("%lld",Ans);
    
    
    }
    

    以后遇到这样的数学推导题,经过一遍草率的推导得到了最终式子的时候,一定要从头认真推导一遍,每一个项都不能忽略

  • 相关阅读:
    .NetCore(四) 在Nginx部署
    .Net Core(三)MVC Core
    .Net Core(二)EFCore
    .Net Core(一)环境搭建与基本使用
    Linux初体验
    Angular基础(八) Observable & RxJS
    Angular基础(七) HTTP & Routing
    Angular基础(六) DI
    Angular基础(五) 内建指令和表单
    Angular基础(四) 创建Angular应用
  • 原文地址:https://www.cnblogs.com/-Iris-/p/15340268.html
Copyright © 2011-2022 走看看