题目描述
小T最近在学着买股票,他得到内部消息:F公司的股票将会疯涨。股票每天的价格已知是正整数,并且由于客观上的原因,最多只能为N。在疯涨的K天中小T观察到:除第一天外每天的股价都比前一天高,且高出的价格(即当天的股价与前一天的股价之差)不会超过M,M为正整数。并且这些参数满足M(K-1)<N。小T忘记了这K天每天的具体股价了,他现在想知道这K天的股价有多少种可能
输入输出格式
输入格式:只有一行用空格隔开的四个数:N、K、M、P。对P的说明参见后面”输出格式“中对P的解释。输入保证20%的数据M,N,K,P<=20000,保证100%的数据M,K,P<=109,N<=1018 。
输出格式:仅包含一个数,表示这K天的股价的可能种数对于P的模值。【输入输出样例】
输入输出样例
输入样例#1:
7 3 2 997
输出样例#1:
16【样例解释】输出样例的16表示输入样例的股价有16种可能:{1,2,3},{1,2,4},{1,3,4},{1,3,5}, {2,3,4},{2,3,5},{2,4,5},{2,4,6}, {3,4,5},{3,4,6},{3,5,6},{3,5,7},{4,5,6},{4,5,7},{4,6,7},{5,6,7}
首先差分价格,得到k-1项数组a[1],a[2],....a[k-1],范围都是[0,M](因为(k-1)*M<N)
设S为a的所有方案,显然|S|=MK-1,对于一个确定的S,它的方案数为第一天可行值
为
$$\sum_{i = 1}^{k-1}a[i]$$
于是有
$$\sum_S N - \sum_{i = 1}^{k-1}a[i]$$ $$N*M^{k-1}-\sum_S\sum_{i = 1}^{k-1}a[i]$$
因为每个a[i]是独立的,确定一个a[i],产生MK-2种方案,权值有(1+2....+M)所以有 $$=N*M^{k-1}-\sum_{i = 1}^{k-1}\sum_Sa[i]$$ $$=N*M^{k-2}-(k-1)*M^{k-2}*(1+2+...+M)$$ $$=N*M^{k-2}-(k-1)*M^{k-2}*{ {M*(M+1)}\over 2}$$
1 #include2 #include 3 #include 4 #include 5 #include 6 using namespace std; 7 typedef long long lol; 8 lol N,K,M,P,ans1,ans2,ans; 9 lol qpow(lol x,lol y)10 {11 lol res=1;12 while (y)13 {14 if (y&1) res=(res*x)%P;15 x=(x*x)%P;16 y/=2;17 }18 return res;19 }20 int main()21 {22 cin>>N>>K>>M>>P;23 N%=P;24 ans1=(qpow(M,K-1)*N)%P;25 ans2=(qpow(M,K-2)*((M*(M+1)/2)%P))%P;26 ans2=((K-1)*ans2)%P;27 ans=(ans1-ans2+P)%P;28 cout<