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