题目描述
小T最近在学着买股票,他得到内部消息:F公司的股票将会疯涨。
股票每天的价格已知是正整数,并且由于客观上的原因,最多只能为N。在疯涨的K天中小T观察到:除第一天外每天的股价都比前一天高,且高出的价格(即当天的股价与前一天 的股价之差)不会超过M,M为正整数。并且这些参数满足m×(k−1)<n。
小T忘记了这K天每天的具体股价了,他现在想知道这K天的股价有多少种可能。
题解
考虑到一个m序列,它对答案的贡献就是n−∑1n−1ain-\sum_1^{n-1} a_in−1∑n−1ai所以答案变成n∗mk−1−∑排列∑ain*m^{k-1}-\sum排列\sum a_in∗mk−1−∑排列∑ai,接着考虑到后面这个aia_iai一共出现了(k−1)∗n∗mk−1(k-1)*n*m^{k-1}(k−1)∗n∗mk−1次,每个数出现的次数又都一样,所以每个数出现了(k−1)∗n∗mk−2(k-1)*n*m^{k-2}(k−1)∗n∗mk−2次,然后就是∑i∗(k−1)∗n∗mk−2\sum i*(k-1)*n*m^{k-2}∑i∗(k−1)∗n∗mk−2 所以总式n∗mk−1−m∗(m+1)/2∗i∗(k−1)∗n∗mk−2n*m^{k-1}-m*(m+1)/2*i*(k-1)*n*m^{k-2}n∗mk−1−m∗(m+1)/2∗i∗(k−1)∗n∗mk−2
##代码
#include <cstdio>
#define LL long long
LL n,k,m,p;
LL Pow(LL x,LL k){
LL res=1;
while(k){
if(k&1) res=res*x%p;
x=x*x%p; k>>=1ll;
}
return res;
}
int main(){
scanf("%lld%lld%lld%lld",&n,&k,&m,&p);
printf("%lld",((n%p*Pow(m,k-1)%p-Pow(m,k-2)%p*(k-1)%p*(m*(m+1)/2%p)%p+p)%p));
return 0;
}