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