P3228 [HNOI2013] 数列 题目分析
题意
小 T 最近在学着买股票,他得到内部消息:F 公司的股票将会疯涨。股票每天的价格已知是正整数,并且由于客观上的原因,最多只能为 \(N\)。在疯涨的 \(K\) 天中小 T 观察到:除第一天外每天的股价都比前一天高,且高出的价格(即当天的股价与前一天的股价之差)不会超过 \(M\),\(M\) 为正整数。并且这些参数满足 \(M(K-1)<N\)。小 T 忘记了这 \(K\) 天每天的具体股价了,他现在想知道这 \(K\) 天的股价有多少种可能。
输入保证 \(20\%\) 的数据 \(M,N,K,P \le 20000\),保证 \(100\%\) 的数据 \(M,K,P \le 10^9\),\(N \le 10^{18}\)。
分析
关键转化成差分数组 \(d\)。
这样:\(1\leq d_i\leq m\),于是 \(\sum_{i=1}^{k-1}d_i\leq m(k-1)<n\)。
所以 \(a_k=a_1+\sum d_i\Rightarrow 1\leq a_1=a_k-\sum d_i\leq n - \sum d_i\)(\(a_k\leq n\))。
于是对于任意的 \(d\),\(a_1\) 都有 \(n-\sum d_i\) 种选择。
于是:
\[\begin{aligned}
ans&=&&\sum_{d_1=1}^m\dots\sum_{d_{k-1}=1}^m\left(n-\sum_{i=1}^{k-1}d_i\right)\\
&=&&m^{k-1}n-\sum_{d_1=1}^m\dots\sum_{d_{k-1}=1}^m(d_1+\dots+d_{k-1})\\
&=&&m^{k-1}n-m^{k-2}\sum_{d_1=1}^md_1-\dots-m^{k-2}\sum_{d_{k-1}=1}^md_{k-1}\\
&=&&m^{k-1}n-m^{k-2}(k-1)\frac{m(m+1)}{2}
\end{aligned}
\]
然后做完了,注意 \(P\) 不一定是质数,而且要先对 \(n\) 取模。
代码
时间复杂度 \(\mathcal{O}(\log (KP))\)。
#include <iostream>
#include <cstring>
#include <algorithm>
#include <stdlib.h>
#include <cstdio>
#include <vector>
#define int long long
#define N 500005
using namespace std;
//const int mod = 1e9 + 7;
int n,k,m,mod;
int qpow(int a,int b) {
int res = 1;
while(b){
if(b & 1) res = res * a % mod;
a = a * a % mod;
b >>= 1;
}
return res;
}
signed main(){
cin >> n >> k >> m >> mod;
n %= mod;
if (k == 1) return cout << n % mod,0;
int t = qpow(m,k - 1);
cout << (t * n % mod - qpow(m,k - 2) * (k - 1) % mod * ((m * (m + 1) / 2) % mod) % mod + mod) % mod;
return 0;
}

浙公网安备 33010602011771号