P3228 BZOJ 3142【HNOI2013 数列】组合数学

Tags : 组合数学

题意分析:

某公司股票疯涨K天,每天涨幅不超过M,最高股价不超过N,求K天股价的种类数,对于种类数模一个质数P,满足M\(\times\)(K-1)\(<\)N


分析:

将这K天的股价可以看成一个序列S[K]
对于这个序列求出它的差分数组A[ ],具有如下的性质:

1.由于S[ ]共有K项,所以它的差分数组共有K-1
2.由M\(\times\)(K-1)\(<\)N可得\(\forall\)A[i]\(<\)M

由以上性质可以推出差分序列的每一项有M种选择,共有K-1项,由组合数学乘法原理可得这个差分序列共有\(m^{k-1}\)种形式

同时,差分序列和原序列并不是一一对应的,每一个原序列由原序列的首项S[1]和差分序列A[K-1]决定,首项的选择范围为\(\lbrack1,n-\sum_{i=1}^{k-1}A[i]\rbrack\),所以每一个差分序列贡献的答案为\(n-\sum_{i=1}^{k-1}A[i]\)

由以上得总的答案:

\[ans=\sum_{j=1}^{m^{k-1}}\left( n-\sum_{i=1}^{k-1}A[i]\right)={n^{m^{k-1}}}+\sum_{j=1}^{m^{k-1}}\sum_{i=1}^{k-1}A[i] \]

现在考虑怎么处理式子最后对于差分数列的求和,由于差分数列没有什么条件约束
联系上文提到的差分数列第二条性质,这\({m^{k-1}\times(k-1)}\)个数在\(\lbrack1,M\rbrack\)内均匀分布
则每个数都会出现\(\frac{m^{k-1}(k-1)}{m}={m^{k-2}\times(k-1)}\)
那么对答案总的贡献为\({m^{k-2}\times(k-1)}\times\frac{m\times{m-1}}{2}\)

所以总的答案为:

\[ans={n^{m^{k-1}}}-{m^{k-2}\times(k-1)}\times\frac{m\times{m-1}}{2} \]


代码时间:

对于上面推出来的数学式子,我们需要写一个快速幂函数来简化运算,计算出\({n^{m^{k-1}}}\)\({m^{k-2}}\)定义成long long类型,同时注意取模,防止数据溢出

#include<bits/stdc++.h>

using namespace std;

namespace zzc
{
    long long n,m,k,mod,sum;
	
	void init()
	{
		scanf("%lld%lld%lld%lld",&n,&k,&m,&mod);
	}
	
	long long qpow(long long a,long long x)
	{
		long long tot=1;
		while(x)
		{
			if(x&1) 
			{
			  tot*=a;
			  tot%=mod;	
			}
			a=a*a;
			a%=mod;
			x>>=1;
		}
		return tot%mod;
	}
	
	void work()
	{
		init();
		if(m&1) sum=m%mod*(m+1)/2%mod;
		else sum=m/2%mod*(m+1)%mod;
		printf("%lld\n",( n%mod*qpow(m,k-1)%mod-sum*(k-1)%mod*qpow(m,k-2)%mod+mod )%mod );
	}
	
}

int main()
{
	zzc::work();
	return 0;
}

有什么问题可以在评论区留言或者私信我,我都会看的

posted @ 2020-07-05 09:34  youth518  阅读(136)  评论(0)    收藏  举报