[HNOI2013]数列
Solution
发现 \(a_1\) 的取值并不固定,所以考虑差分序列,这样就不用考虑 \(a_1\) 了。
由于相邻两天的差不超过 \(m\),也就是差分序列上的元素不超过 \(m\)。并且有 \(k\) 天,那么这个序列的元素个数是 \(k-1\)。
我们考虑对于一个差分序列 \(S\),如果其中的元素已经确定,那么最终的答案个数是 \(n-\sum\limits_{i=1}^{k-1} S_i\)。也就是 \(a_1\) 的取值个数。
然后观察题目 \(m\times (k-1)<n\),也就是说就算每天都增长 \(m\) 最后也至少有一个 \(a_1\) 的取值是满足的。所以可以简单认为,\(S\) 的方案数就是 \(m^{k-1}\)。
接下来我们设 \(S_i\) 为第 \(i\) 种差分序列,那么答案就是:
\[\sum_{i=1}^{m^{k-1}}(n-\sum_{j=1}^{k-1} S_{i,j})
\]
\[=m^{k-1}\times n-\sum_{i=1}^{m^{k-1}}\sum_{j=1}^{k-1} S_{i,j}
\]
然后我们考虑求后面那一坨的东西。
直接做大概会 GG,所以考虑其意义。其实就是对于差分序列上的每个位置,所有取值的和。容易得到,对于一个位置上的一个值,总共出现了 \(m^{k-2}\) 次。也就是说:
\[\sum_{i=1}^{m^{k-1}}\sum_{j=1}^{k-1} S_{i,j}=m^{k-2}\times (k-1)\times \sum_{i=1}^mi=m^{k-2}\times (k-1)\times \dfrac{m\times (m+1)}{2}
\]
然后就做完了。
Code
// Problem: P3228 [HNOI2013]数列
// Contest: Luogu
// URL: https://www.luogu.com.cn/problem/P3228
// Memory Limit: 125 MB
// Time Limit: 1000 ms
// Author: ZCETHAN
// Time: 2021-11-10 13:59:12
#include<bits/stdc++.h>
#define ll long long
#define inf (1<<30)
#define INF (1ll<<60)
using namespace std;
ll MOD;
ll ksm(ll a,ll p){
ll ret=1;while(p){
if(p&1) ret=ret*a%MOD;
a=a*a%MOD; p>>=1;
}return ret;
}
int main()
{
ll n,k,m;
scanf("%lld%lld%lld%lld",&n,&k,&m,&MOD);
n%=MOD;m%=MOD;
ll x=ksm(m,k-1)*n%MOD;
ll y=(m*(m+1)/2)%MOD*(k-1)%MOD*ksm(m,k-2)%MOD;
printf("%lld\n",((x-y)%MOD+MOD)%MOD);
return 0;
}