2019HDU多校第九场 Rikka with Quicksort —— 数学推导&&分段打表
题意
设
$$g_m(n)=\begin{cases}
& g_m(i) = 0, \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ 0 \leq i \leq m\\
& g_m(i) = i-1 + \frac{1}{i}\sum _{j=1}^i(g_m(j) + g_m(i-j)), \ \ i > m\\
\end{cases}$$
现给出 $n$ 和 $m$,求 $g_m(n)$ 模 $1000000007$.
分析
当 $n>m$ 时,易知 $a_n = n-1 + \frac{2}{n} S_{n-1}$,
即 $S_n - S_{n-1} = n-1 + \frac{2}{n} S_{n-1}$,
变形得 $\frac{S_n}{(n+1)(n+2)} = \frac{n-1}{(n+1)(n+2)} + \frac{S_{n-1}}{n(n+1)}$.
令 $b_n = \frac{S_n}{(n+1)(n+2)}$,得 $b_n = \frac{n-1}{(n+1)(n+2)} + b_{n-1}$,
变形 $b_n - b_{n-1} = \frac{3}{n+2} - \frac{2}{n+1} = 2(\frac{1}{n+2}-\frac{1}{n+1}) + \frac{1}{n+2}$,
根据裂项相消得 $b_n - b_m = 2(\frac{1}{n+2} - \frac{1}{m+2}) + \frac{1}{m+3} + \frac{1}{m+4}+...+\frac{1}{n+2}$,
即 $b_n = 2(\frac{1}{n+2} - \frac{1}{m+2}) + S(n+2)-S(m+2)$.
其中 $S(n)$ 表示前 $n$ 个倒数和,可以分段打表。
( $1e4$ 的表虽然不会超内存限制,但是会超代码长度限制www,最后改成2000
#include<bits/stdc++.h> using namespace std; typedef long long ll; const ll mod = 1000000007; const int maxn = 1e9 + 10; const int siz = 500000; //2000 int f[maxn/siz+10] = {{0,389417116,881884276,553560598,224432428,260751735,117569315,...} //省略了 ll n, m; ll qpow(ll a, ll b, ll p) { ll ret = 1; while(b) { if(b&1) ret = ret * a % p; a = a * a % p; b >>= 1; } return ret; } ll inv(ll n) { return qpow(n, mod-2, mod); } ll S(ll n) { int k = n / siz; //printf("%d\n", k); ll tmp = f[k]; for(int i = k*siz+1;i <= n;i++) tmp = (tmp + inv(i)) % mod; return tmp; } int main() { int T; scanf("%d", &T); while(T--) { scanf("%lld%lld", &n, &m); ll bn = (2*(inv(n+2) - inv(m+2)) + S(n+2) - S(m+2)) % mod; ll bn_1 = (2*(inv(n+1) - inv(m+2)) + S(n+1) - S(m+2)) % mod; ll sn = (n+1) * (n+2) % mod * bn % mod; ll sn_1 = n * (n+1) % mod * bn_1 % mod; printf("%lld\n", (sn - sn_1 + 2*mod) % mod); } }
参考链接:https://blog.csdn.net/baiyifeifei/article/details/99892190