UPD
Orz zyf的生成函数解法
Problem
Solution
我们考虑每天的增幅对答案的贡献。不妨设其为数列 a[1..k−1],a[i]∈[1,m] a [ 1.. k − 1 ] , a [ i ] ∈ [ 1 , m ]
因为第一天的初值可以在 [1,n−∑k−1i=1a[i]] [ 1 , n − ∑ i = 1 k − 1 a [ i ] ] 中平移,则其对答案的贡献为 n−∑k−1i=1a[i] n − ∑ i = 1 k − 1 a [ i ] 。
那么我们会发现,一共有 mk−1 m k − 1 个不同的数列a,一共 (k−1)∗mk−1 ( k − 1 ) ∗ m k − 1 个数,而对于每一个[1,m]内的数,出现次数都相同,也就是说都会出现 (k−1)∗mk−2 ( k − 1 ) ∗ m k − 2 次。
提出前面的n,我们可以发现答案就是 n∗mk−1−(k−1)∗mk−2(∑mi=1i) n ∗ m k − 1 − ( k − 1 ) ∗ m k − 2 ( ∑ i = 1 m i )
Code
#include <cstdio>
using namespace std;
typedef long long ll;
ll n,m,k,p,ans;
ll power(ll x,ll y)
{
ll res=1;
while(y)
{
if(y&1) res=res*x%p;
x=x*x%p;
y>>=1;
}
return res;
}
int main()
{
scanf("%lld%lld%lld%lld",&n,&k,&m,&p);
n=n%p;
ans=(power(m % p,k-1)*(n%p))%p;
ans-=((power(m % p,k-2)*(k-1)% p)*(((m+1)*m/2)% p))%p;
ans=(ans+p)%p;
printf("%lld\n",ans);
return 0;
}