bzoj3142[HNOI2013]数列

五分钟就推完了...
如果模数为质数还有一些简单的搞法,不是质数我好像只想到这一种简便一点的。
枚举每天与前一天的差值,第一天有 n-差值之和 的取法:

\[\sum_{x_1=1}^M \sum_{x_2=1}^M ... \sum_{x_{k-1}=1}^M (N-\sum_{i=1}^{k-1}x_i) \]

\[ans=M^{k-1}*N-\sum_{x_1=1}^M \sum_{x_2=1}^M ... \sum_{x_{k-1}=1}^M(\sum_{i=1}^{k-1} x_i) \]

\(g(i)=\sum_{x_1=1}^M \sum_{x_2=1}^M ... \sum_{x_{i}=1}^M (\sum_{j=1}^i x_i)\)
g是可以递推的。

\[g(i)=\sum_{x_1=1}^M ...\sum_{x_{i-1}=1}^M \sum_{x_{i}=1}^M (x_1+...+x_{i-1}+x_i) \]

\[=\sum_{x_1=1}^M ...\sum_{x_{i-1}=1}^M(M*\sum_{j=1}^{i-1}x_j+\sum_{x_i=1}^M x_i) \]

\[=M*\sum_{x_1=1}^M ...\sum_{x_{i-1}=1}^M (\sum_{j=1}^{i-1}x_j) + M^{i-1}*\frac{M*(M+1)}{2} \]

\[=M*g(i-1)+M^{i-1}*\frac{M*(M+1)}{2} \]

首先\(g(1)=\frac{M*(M+1)}{2},g(2)=2*M*\frac{M*(M+1)}{2}\),我们会去猜想\(g(k)=k*M^{k-1}*\frac{M*(M+1)}{2}\)
然后就是简单的用数学归纳法证明了,假设我们知道了对于\(i=k\)时成立,有\(g(k)=k*M^{k-1}*\frac{M*(M+1)}{2}\),那么\(g(k+1)=M*g(k)+M^k*\frac{M*(M+1)}{2}=k*M^k*\frac{M*(M+1)}{2}+M^k*\frac{M*(M+1)}{2}=(k+1)*M^k*\frac{M*(M+1)}{2}\),所以对于任意\(i\in N^{*}\),猜想成立。
(当然也可以得到\(\frac{g(i)}{M^i}=\frac{g(i-1)}{M^{i-1}}+\frac{(M+1)}{2}\)就可以直接算通项了)
所以答案就是

\[M^{k-1}*N-g(k-1) \]

\[=M^{k-1}*N-(k-1)*M^{k-2}*\frac{M*(M+1)}{2} \]

特判一下\(k=1\)的情况。

#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#include<cmath>
#include<vector>
#define pl puts("lala")
#define cp cerr<<"lala"<<endl
#define fi first
#define se second
#define pb push_back
#define ln putchar('\n')
using namespace std;
inline int read()
{
	char ch=getchar();int g=1,re=0;
	while(ch<'0'||ch>'9') {if(ch=='-')g=-1;ch=getchar();}
	while(ch<='9'&&ch>='0') re=(re<<1)+(re<<3)+(ch^48),ch=getchar();
	return re*g;
}
typedef long long ll;
typedef pair<int,int> pii;

int mod;
ll qpow(ll a,int n)
{
	ll ans=1;
	for(;n;n>>=1,a=a*a%mod) if(n&1) ans=ans*a%mod;
	return ans;
}
ll n;
int m,k;

int main()
{
#ifndef ONLINE_JUDGE
	freopen("1.in","r",stdin);freopen("1.out","w",stdout);
#endif
	scanf("%lld%d%d%d",&n,&k,&m,&mod);
	n%=mod;
	if(k==1) printf("%lld\n",n);
	else printf("%lld\n",(qpow(m,k-1)*n%mod
	-1ll*m*(m+1)/2%mod*(k-1)%mod*qpow(m,k-2)%mod+mod)%mod);
	return 0;
}
posted @ 2018-04-05 12:03  BLMontgomery  阅读(158)  评论(0编辑  收藏  举报