bzoj3142: [Hnoi2013]数列

传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=3142

思路:首先我们假设初值固定,无视上限,那么我们就可以看成是走K-1步,每步有M种走法

那方案数就是M^(k-1)

但是初值不固定,枚举是不现实的,因为如果起点较为靠后,我们就不能无视上限,方案是无法统计的

但这给我们一个启示,走的每步不就是差分数组吗

于是我们可以考虑对于一个差分数组a[i],它对答案有多少贡献

我们可以靠移动首位来得到不同方案

就是n-Σa[i]

那么总方案就是

ΣΣΣ....Σ(n-a[1]-a[2]-....-a[K-1])

提出n

M^(K-1)*n-ΣΣΣ....Σ(a[1]+a[2]+....+a[K-1])

对于右边的部分

统计一位的值,我们可以取(1->M),然后我们有(K-1)个不同的位置,固定后仍有(K-2)个位置可取(1-M)的任意值,于是有

M^(K-2)的方案

于是可化为(1+2+3+.....+m)*(K-1)*M^(K-2),即(M*(M+1)/2)*(K-1)*M^(K-2)

答案就是M^(K-1)*n-(M*(M+1)/2)*(K-1)*M^(K-2)

#include<cstdio>
using namespace std;
typedef long long ll;
ll n,k,m,mod;

ll mypw(ll a,ll b){
	ll res=1,j=a;
	for (;b;b>>=1,j=j*j%mod) if (b&1) res=res*j%mod;
	return res;
}

int main(){
	scanf("%lld%lld%lld%lld",&n,&k,&m,&mod);
	ll ans1=mypw(m,k-2),ans2=ans1*m%mod;
	if (k==1) return printf("%lld\n",n%mod),0;
	printf("%lld\n",(n%mod*ans2%mod-m*(m+1)/2%mod*ans1%mod*(k-1)%mod+mod)%mod);
	return 0;
}



posted @ 2015-12-28 15:17  orzpps  阅读(117)  评论(0编辑  收藏  举报