题解 P3228 【[HNOI2013]数列】
无耻的安利一波博客Chlience
这个题目我们可以画图AC
将某一个确定的上涨序列
这个序列对于总数的贡献为1,当然,是当
显然的,维持每天上涨的价格不变,由于
那么能不能考虑维护一个股票价格的差分数列?就不用考虑
并且,这个差分数列
一共有
那么总贡献就为
将
现在要做的就是处理后面那一堆东西
注意,
那么后面一共就会有
所以
运用小学数学知识,将其总和化为
这样就很好求解了
最终答案为
努力追赶dalao中 给予我力量吧(丢脸ing
代码如下
#include <bits/stdc++.h>
using namespace std;
#define ll long long
ll n,k,m,p,ans;
ll read() {
ll ans=0,flag=1;
char ch=getchar();
while((ch>'9' || ch<'0') && ch!='-') ch=getchar();
if(ch=='-') flag=-1,ch=getchar();
while(ch>='0' && ch<='9') ans=ans*10+ch-'0',ch=getchar();
return ans*flag;
}
ll qpow(ll a,ll b,ll mod) {
ll ans=1;
while(b>0) {
if(b&1) {ans*=a;ans%=mod;}
b>>=1;a*=a;a%=mod;
}
return ans;
}
ll exgcd(ll a,ll b,ll &x,ll &y) {
if(b==0) {x=1;y=0;return a;}
ll gcd=exgcd(b,a%b,x,y);
ll t=x;
x=y; y=t-(a/b)*y;
}
int main() {
n=read(),k=read(),m=read(),p=read();
ll x,y,gcd;
gcd=exgcd(2,p,x,y);
x=(x%p+p)%p;
ans+=(qpow(m,k-1,p)*(n%p))%p;
ans-=((((qpow(m,k-1,p)*(k-1))%p*(m+1))%p)%p*x%p);
ans=(ans%p+p)%p;
printf("%lld\n",ans);
return 0;
}