【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; }