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]\)
由以上得总的答案:
现在考虑怎么处理式子最后对于差分数列的求和,由于差分数列没有什么条件约束
联系上文提到的差分数列第二条性质,这\({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}\)
所以总的答案为:
代码时间:
对于上面推出来的数学式子,我们需要写一个快速幂函数来简化运算,计算出\({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;
}
有什么问题可以在评论区留言或者私信我,我都会看的