【bzoj3142】[Hnoi2013]数列 数学

题目描述

求满足 $1\le a_i\le n\ ,\ 1\le a_{i+1}-a_i\le m$ 的序列 $a_1...a_k$ 的个数模 $p$ 的值。

输入

只有一行用空格隔开的四个数:N、K、M、P。对P的说明参见后面“输出格式”中对P的解释。
输入保证20%的数据M,N,K,P≤20000,保证100%的数据M,K,P≤109,N≤1018 。

输出

仅包含一个数,表示这K天的股价的可能种数对于P的模值。

样例输入

7 3 2 997

样例输出

16


题解

数学

设第 $i$ 天与第 $i+1$ 天的差为 $a_i$,那么显然答案为:

$\sum\limits_{a_1=1}^m\sum\limits_{a_2=1}^m...\sum\limits_{a_{k-1}=1}^m(n-a_1-a_2-...-a_{k-1})$

考虑这个式子是什么:

由于每个数有 $m$ 种取值,因此相当于有 $m^{k-1}$ 次加和, $n$ 的那一部分答案为 $n·m^{k-1}$

思考后面的部分$\sum\limits_{a_1=1}^m\sum\limits_{a_2=1}^m...\sum\limits_{a_{k-1}=1}^m(a_1+a_2+...+a_{k-1})$,考虑每个数的贡献:该数每一个取值对应着 $m^{k-2}$ 次加和,所以每个数的贡献为 $m^{k-2}·\sum\limits_{i=1}^mi=\frac{(m+1)m^{k-1}}2$,因此总和为 $\frac{(k-1)(m+1)m^{k-1}}2$

最终答案即为 $n·m^{k-1}-\frac{(k-1)(m+1)m^{k-1}}2=\frac{m^{k-1}(2n-(k-1)(m+1))}2$,使用快速幂计算即可。

注意这个除2比较难以处理,考虑将模数*2变为偶数,那么原答案的奇偶性不变,可以直接除2。

千万要注意取模的问题!

#include <cstdio>
typedef long long ll;
ll n , k , m , p;
ll pow(ll x , ll y)
{
	ll ans = 1;
	while(y)
	{
		if(y & 1) ans = ans * x % p;
		x = x * x % p , y >>= 1;
	}
	return ans;
}
int main()
{
	scanf("%lld%lld%lld%lld" , &n , &k , &m , &p) , p <<= 1;
	printf("%lld\n" , (pow(m , k - 1) * (2 * n % p - (m + 1) * (k - 1) % p) / 2 % p + p) % (p >> 1));
	return 0;
}

 

 

posted @ 2017-11-10 14:56  GXZlegend  阅读(329)  评论(0编辑  收藏  举报