垃圾ACMer的暑假训练220716
Codeforces
Codeforces Round #807 (Div. 2) A. Mark the Photographer
原题指路:https://codeforces.com/contest/1705/problem/A
题意
现要给编号 1 ∼ 2 n 1\sim 2n 1∼2n的 2 n 2n 2n个人拍照,其中第 i ( 1 ≤ i ≤ 2 n ) i\ \ (1\leq i\leq 2n) i (1≤i≤2n)个人的身高为 h i h_i hi.现 2 n 2n 2n个人排成两行,每行 n n n个人,要求后一行的第 j ( 1 ≤ j ≤ n ) j\ \ (1\leq j\leq n) j (1≤j≤n)个人至少比前一行的第 j j j个人高 x x x.问是否能做到.
有 t ( 1 ≤ t ≤ 100 ) t\ \ (1\leq t\leq 100) t (1≤t≤100)组测试数据.每组测试数据第一行输入整数 n , x ( 1 ≤ n ≤ 100 , 1 ≤ x ≤ 1000 ) n,x\ \ (1\leq n\leq 100,1\leq x\leq 1000) n,x (1≤n≤100,1≤x≤1000).第二行输入 2 n 2n 2n个数 h 1 , ⋯ , h 2 n ( 1 ≤ h i ≤ 1000 ) h_1,\cdots,h_{2n}\ \ (1\leq h_i\leq 1000) h1,⋯,h2n (1≤hi≤1000),分别表示每个人的身高.
对每组测试数据,若能做到,输出"YES";否则输出"NO".
思路
将 h [ ] h[] h[]升序排列后,只需保证 h n + i − h i ≥ x ( 1 ≤ i ≤ n ) h_{n+i}-h_i\geq x\ \ (1\leq i\leq n) hn+i−hi≥x (1≤i≤n).
[证] 注意到 h [ ] h[] h[]升序排列后,有 ( n + 1 ) (n+1) (n+1)个人身高在 [ h i , h n + i ] [h_i,h_{n+i}] [hi,hn+i]范围内.
因每行至多 n n n人,则这 ( n + 1 ) (n+1) (n+1)个人中至少有两人在同一列,故只需 h n + i − h i ≥ x h_{n+i}-h_i\geq x hn+i−hi≥x.
代码
int main() {
CaseT{
int n,x; cin >> n >> x;
vi h(2 * n);
for (int i = 0; i < 2 * n; i++) cin >> h[i];
sort(all(h));
bool flag = true;
for (int i = 0; i < n; i++) {
if (h[i + n] - h[i] < x) {
flag = false;
break;
}
}
if (flag) cout << "YES" << endl;
else cout << "NO" << endl;
}
}
Codeforces Round #807 (Div. 2) B. Mark the Dust Sweeper
原题指路:https://codeforces.com/contest/1705/problem/B
题意 ( 1.5 s 1.5\ \mathrm{s} 1.5 s)
初始时有 n n n个数 a 1 , ⋯ , a n a_1,\cdots,a_n a1,⋯,an.现可进行如下操作:选择一对下标 ( i , j ) s . t . a i , ⋯ , a j − 1 > 0 (i,j)\ s.t.\ a_i,\cdots,a_{j-1}>0 (i,j) s.t. ai,⋯,aj−1>0,然后 a i − − , a j + + a_i--,a_j++ ai−−,aj++.现需经若干次操作后能 s . t . a 1 = a 2 = ⋯ = a n − 1 = 0 \ s.t.\ a_1=a_2=\cdots=a_{n-1}=0 s.t. a1=a2=⋯=an−1=0.
有 t ( 1 ≤ t ≤ 1 e 4 ) t\ \ (1\leq t\leq 1\mathrm{e}4) t (1≤t≤1e4)组测试数据.每组测试数据第一行输入整数 n ( 2 ≤ n ≤ 2 e 5 ) n\ \ (2\leq n\leq 2\mathrm{e}5) n (2≤n≤2e5),表示序列长度.第二行输入 n n n个整数 a 1 , ⋯ , a n ( 0 ≤ a i ≤ 1 e 9 ) a_1,\cdots,a_n\ \ (0\leq a_i\leq 1\mathrm{e}9) a1,⋯,an (0≤ai≤1e9).数据保证所有测试数据的 n n n之和不超过 2 e 5 2\mathrm{e}5 2e5.
对每组测试数据,输出最小步数.数据保证有解.
思路I
观察样例猜测:有解的序列的前 ( n − 1 ) (n-1) (n−1)中非零数的左右都是 0 0 0.
模拟样例 0 2 0 3 0 0\ 2\ 0\ 3\ 0 0 2 0 3 0:
下标 | 1 1 1 | 2 2 2 | 3 3 3 | 4 4 4 | 5 5 5 |
---|---|---|---|---|---|
数值 | 0 0 0 | 2 2 2 | 0 0 0 | 3 3 3 | 0 0 0 |
①取 ( i , j ) = ( 2 , 3 ) (i,j)=(2,3) (i,j)=(2,3),显然 a 2 = 2 > 0 a_{2}=2>0 a2=2>0,序列变为:
下标 | 1 1 1 | 2 2 2 | 3 3 3 | 4 4 4 | 5 5 5 |
---|---|---|---|---|---|
数值 | 0 0 0 | 1 1 1 | 1 1 1 | 3 3 3 | 0 0 0 |
②取 ( i , j ) = ( 4 , 5 ) (i,j)=(4,5) (i,j)=(4,5),显然 a 4 = 3 > 0 a_4=3>0 a4=3>0,序列变为:
下标 | 1 1 1 | 2 2 2 | 3 3 3 | 4 4 4 | 5 5 5 |
---|---|---|---|---|---|
数值 | 0 0 0 | 1 1 1 | 1 1 1 | 2 2 2 | 1 1 1 |
③取 ( i , j ) = ( 4 , 5 ) (i,j)=(4,5) (i,j)=(4,5),显然 a 4 = 2 > 0 a_4=2>0 a4=2>0,序列变为:
下标 | 1 1 1 | 2 2 2 | 3 3 3 | 4 4 4 | 5 5 5 |
---|---|---|---|---|---|
数值 | 0 0 0 | 1 1 1 | 1 1 1 | 1 1 1 | 2 2 2 |
④取 ( i , j ) = ( 2 , 5 ) (i,j)=(2,5) (i,j)=(2,5),显然 a 2 = 1 > 0 , a 3 = 1 > 0 , a 4 = 1 > 0 a_2=1>0,a_3=1>0,a_4=1>0 a2=1>0,a3=1>0,a4=1>0,序列变为:
下标 | 1 1 1 | 2 2 2 | 3 3 3 | 4 4 4 | 5 5 5 |
---|---|---|---|---|---|
数值 | 0 0 0 | 0 0 0 | 1 1 1 | 1 1 1 | 3 3 3 |
⑤取 ( i , j ) = ( 3 , 5 ) (i,j)=(3,5) (i,j)=(3,5),显然 a 3 = 1 > 0 , a 4 = 1 > 0 a_3=1>0,a_4=1>0 a3=1>0,a4=1>0,序列变为:
下标 | 1 1 1 | 2 2 2 | 3 3 3 | 4 4 4 | 5 5 5 |
---|---|---|---|---|---|
数值 | 0 0 0 | 0 0 0 | 0 0 0 | 1 1 1 | 4 4 4 |
⑥取 ( i , j ) = ( 4 , 5 ) (i,j)=(4,5) (i,j)=(4,5),显然 a 4 = 1 > 0 a_4=1>0 a4=1>0,序列变为:
下标 | 1 1 1 | 2 2 2 | 3 3 3 | 4 4 4 | 5 5 5 |
---|---|---|---|---|---|
数值 | 0 0 0 | 0 0 0 | 0 0 0 | 0 0 0 | 5 5 5 |
注意到一次操作只能改变两个数,故上述每个非零数分别处理的步数是最少的.
手模样例知:每个非零数 x x x都会需 ( x − 1 ) (x-1) (x−1)步变为 0 0 0,且从第一个非零数开始到第 ( n − 1 ) (n-1) (n−1)个数的位置在途中都会出现 1 1 1,故还需 ( n − i d x − 1 ) (n-idx-1) (n−idx−1)步.
代码I
int main() {
CaseT{
int n; cin >> n;
vi a(n);
ll ans = 0;
int idx = -1;
for (int i = 0; i < n; i++) {
cin >> a[i];
if (i != n - 1 && a[i]) {
ans += a[i] - 1;
if (idx == -1) idx = i;
}
}
if (~idx) ans += (ll)n - idx - 1;
cout << ans << endl;
}
}
思路II
删除序列的前导零,设当前 a 1 ≠ 0 , k a_1\neq 0,k a1=0,k为 a 1 , ⋯ , a n − 1 a_1,\cdots,a_{n-1} a1,⋯,an−1中 0 0 0的个数,则 a n s = ( a 1 + ⋯ + a n − 1 ) + k ans=(a_1+\cdots+a_{n-1})+k ans=(a1+⋯+an−1)+k.
[证] 设先将序列中所有的 0 0 0变为 1 1 1,即取 i i i为第一个非零数的下标, j j j为第一个 0 0 0的下标,做一次操作.
将 a 1 , ⋯ , a n − 1 a_1,\cdots,a_{n-1} a1,⋯,an−1中的所有 0 0 0变为 1 1 1需 k k k次操作.
从左往右依次取 i i i为第一个非零数的下标, j = n j=n j=n,做 ( a 1 + ⋯ + a n − 1 ) (a_1+\cdots+a_{n-1}) (a1+⋯+an−1)次操作将 a 1 , ⋯ , a n − 1 a_1,\cdots,a_{n-1} a1,⋯,an−1变为 0 0 0.
下面证明这样的步数最小,只需证明每次操作至多只会让 a n s ans ans减少 1 1 1.
①若操作的 j = n j=n j=n,则它会使得 ( a 1 + ⋯ + a n − 1 ) (a_1+\cdots+a_{n-1}) (a1+⋯+an−1)减少 1 1 1.
②若操作的 j ≠ n j\neq n j=n,则它不会减少 ( a 1 + ⋯ + a n − 1 ) (a_1+\cdots+a_{n-1}) (a1+⋯+an−1),但至多会让 k k k减少 1 1 1.
代码II
int main() {
CaseT{
int n; cin >> n;
vi a(n);
for (int i = 0; i < n; i++) cin >> a[i];
int start = 0; // 指向序列的第一个非零数
while (start < n && !a[start]) start++;
ll ans = 0;
for (int i = start; i < n - 1; i++) {
ans += a[i];
if (!a[i]) ans++;
}
cout << ans << endl;
}
}
Codeforces Round #807 (Div. 2) C. Mark and His Unfinished Essay
原题指路:https://codeforces.com/contest/1705/problem/C
题意 ( 2 s 2\ \mathrm{s} 2 s)
给定一个长度为 n n n的字符串 s s s,下标从 1 1 1开始.现有 c c c次操作,每次取区间 [ l , r ] [l,r] [l,r],将 s [ l ⋯ r ] s[l\cdots r] s[l⋯r]接到 s s s的后面.操作结束后有 q q q个询问,每个询问给定一个数 k k k,输出当前字符串的第 k k k个字符.
有 t ( 1 ≤ t ≤ 1000 ) t\ \ (1\leq t\leq 1000) t (1≤t≤1000)组测试数据.每组测试数据第一行输入三个整数 n , c , q ( 1 ≤ n ≤ 2 e 5 , 1 ≤ c ≤ 40 , 1 ≤ q ≤ 1 e 4 ) n,c,q\ \ (1\leq n\leq 2\mathrm{e}5,1\leq c\leq 40,1\leq q\leq 1\mathrm{e}4) n,c,q (1≤n≤2e5,1≤c≤40,1≤q≤1e4).第二行输入长度为 n n n的初始字符串 s s s.接下来 c c c行每行输入两个整数 [ l , r ] ( 1 ≤ l ≤ r ≤ 1 e 18 ) [l,r]\ \ (1\leq l\leq r\leq 1\mathrm{e}18) [l,r] (1≤l≤r≤1e18),表示要操作的区间,数据保证 r r r不超过当前字符串的长度.接下来 q q q行每行输入一个整数 k ( 1 ≤ k ≤ 1 e 18 ) k\ \ (1\leq k\leq 1\mathrm{e}18) k (1≤k≤1e18),表示询问的下标,数据保证 k k k不超过当前字符串的长度.数据保证所有测试数据的 n n n之和不超过 2 e 5 2\mathrm{e}5 2e5, q q q之和不超过 1 e 4 1\mathrm{e}4 1e4.
对每个询问,输出当前字符串的第 k k k个字符.
思路I
维护每次操作后字符串的长度的前缀和 p r e [ ] pre[] pre[].对每个询问 k k k,找到下标 k k k在哪一段区间中,并递推找到上一段区间.时间复杂度 O ( c q ) O(cq) O(cq).
若每次询问都二分,时间复杂度 O ( ( c log c ) q ) O((c\log c)q) O((clogc)q),不如直接递推.
代码I
int main() {
CaseT{
int n,c,q; cin >> n >> c >> q;
string s; cin >> s;
vl l(c), r(c); // 操作区间的左右端点
vl len(c + 1); // 序列长度的前缀和
len[0] = n; // 初始长度
for (int i = 0; i < c; i++) {
cin >> l[i] >> r[i];
len[i + 1] = len[i] + r[i] - l[i] + 1;
}
while (q--) {
ll k; cin >> k;
for (int i = c - 1; i >= 0; i--) // 找到k属于第几段区间
if (k > len[i]) k = l[i] + (k - len[i] - 1); // 递推到上一个区间
cout << s[k - 1] << endl;
}
}
}
思路II
对第 i i i次操作,记录改变的字符串的起点 l e f t i left_i lefti和终点 r i g h t i right_i righti,并记录相邻两区间左端点的距离 d i f f i diff_i diffi,则对 k ∈ [ l e f t i , r i g h t i ] k\in[left_i,right_i] k∈[lefti,righti],第 k k k个字符与第 ( k − d i f f ) (k-diff) (k−diff)个字符相同,递推到初始字符串的区间即可.时间复杂度 O ( c q ) O(cq) O(cq).
代码II
int main() {
CaseT{
int n,c,q; cin >> n >> c >> q;
string s; cin >> s;
vl left(c + 1), right(c + 1); // 操作区间的左右端点
left[0] = 0, right[0] = n; // 原字符串
vl diff(c + 1); // 相邻两区间的左端点的距离
for (int i = 1; i <= c; i++) {
ll l, r; cin >> l >> r;
l--, r--;
left[i] = right[i - 1]; // 当前区间的起点是上一个区间的终点
right[i] = left[i] + (r - l + 1);
diff[i] = left[i] - l;
}
while (q--) {
ll k; cin >> k;
k--;
for (int i = c; i; i--) {
if (k < left[i]) continue;
else k -= diff[i];
}
cout << s[k] << endl;
}
}
}
思路III
DFS递归.
代码III
int main() {
CaseT{
int n,c,q; cin >> n >> c >> q;
string s; cin >> s;
vl len(c + 1); // 序列长度的前缀和
len[0] = n; // 初始长度
vll segs(c + 1);
for (int i = 1; i <= c; i++) {
cin >> segs[i].first >> segs[i].second;
len[i] = len[i - 1] + segs[i].second - segs[i].first + 1;
}
function<char(int, ll)> dfs = [&](int pos, ll k)->char { // 求第pos个区间的第k个字符
if (!pos) return s[k - 1];
ll cur = segs[pos].first - len[pos - 1] + k - 1;
int idx = pos;
while (idx - 1 >= 0 && len[idx - 1] >= cur) idx--;
return dfs(idx, cur);
};
while (q--) {
ll k; cin >> k;
int idx = 0;
for (int i = 0; i <= c; i++) {
if (len[i] >= k) {
idx = i;
break;
}
}
cout << dfs(idx, k) << endl;
}
}
}
Codeforces Round #807 (Div. 2) D. Mark and Lightbulbs
原题指路:https://codeforces.com/contest/1705/problem/D
题意 ( 1.5 s 1.5\ \mathrm{s} 1.5 s)
有一个长度为 n n n的二进制串 s = s 1 s 2 ⋯ s n s=s_1s_2\cdots s_n s=s1s2⋯sn.现可进行操作:取一个下标 i ∈ [ 2 , n − 1 ] s . t . s i − 1 ≠ s i + 1 i\in[2,n-1]\ s.t.\ s_{i-1}\neq s_{i+1} i∈[2,n−1] s.t. si−1=si+1,反转 s i s_i si的值.
有 t ( 1 ≤ t ≤ 1 e 4 ) t\ \ (1\leq t\leq 1\mathrm{e}4) t (1≤t≤1e4)组测试数据.每组测试数据第一行输入一个整数 n ( 3 ≤ n ≤ 2 e 5 ) n\ \ (3\leq n\leq 2\mathrm{e}5) n (3≤n≤2e5),表示二进制串的长度.第二行和第三行分别输入两长度为 n n n的二进制串 s s s和 t t t.数据保证所有测试数据的 n n n之和不超过 2 e 5 2\mathrm{e}5 2e5.
对每组测试数据,若 s s s能经若干次操作变为 t t t,则输出最小步数;否则输出 − 1 -1 −1.
思路
显然若 s [ 0 ] ≠ t [ 0 ] s[0]\neq t[0] s[0]=t[0]或 s [ n − 1 ] ≠ t [ n − 1 ] s[n-1]\neq t[n-1] s[n−1]=t[n−1],则无解.
对长度为 n n n的二进制串 s s s,构造长度为 ( n − 1 ) (n-1) (n−1)的二进制串 s ‾ = ( s 1 x o r s 2 ) ( s 2 x o r s 3 ) ⋯ ( s n − 1 x o r s n ) \overline s=(s_1\ \mathrm{xor}\ s_2)(s_2\ \mathrm{xor}\ s_3)\cdots(s_{n-1}\ \mathrm{xor}\ s_n) s=(s1 xor s2)(s2 xor s3)⋯(sn−1 xor sn),则对 s s s的操作即交换 s ‾ \overline s s相邻的两bit.
以 s = 000101 → t = 010011 s=000101\rightarrow t=010011 s=000101→t=010011为例:
步数 | 1 1 1 | 2 2 2 | 3 3 3 | 4 4 4 | 5 5 5 | 6 6 6 |
---|---|---|---|---|---|---|
s s s | 000101 000101 000101 | 001101 001101 001101 | 011101 011101 011101 | 011001 011001 011001 | 011011 011011 011011 | 010011 010011 010011 |
s ‾ \overline s s | 00111 00111 00111 | 01011 01011 01011 | 10011 10011 10011 | 10101 10101 10101 | 10110 10110 10110 | 11010 11010 11010 |
故 s s s经若干次操作可变为 t t t当且仅当 s ‾ \overline{s} s与 t ‾ \overline t t中的 1 1 1的个数相等.设 s ‾ \overline s s中 1 1 1的位置分别为 a 1 , ⋯ , a k , t ‾ a_1,\cdots,a_k,\overline t a1,⋯,ak,t中 1 1 1的位置分别为 b 1 , ⋯ , b k b_1,\cdots,b_k b1,⋯,bk,则 a n s = ∣ a 1 − b 1 ∣ + ∣ a 2 − b 2 ∣ + ⋯ + ∣ a k − b k ∣ ans=|a_1-b_1|+|a_2-b_2|+\cdots+|a_k-b_k| ans=∣a1−b1∣+∣a2−b2∣+⋯+∣ak−bk∣,这是因为最优策略中 s ‾ \overline s s最左边的 1 1 1与 t ‾ \overline t t最左边的 1 1 1配对, s ‾ \overline s s次左边的 1 1 1与 t ‾ \overline t t次左边的 1 1 1配对, ⋯ \cdots ⋯.时间复杂度 O ( n ) O(n) O(n).
代码
int main() {
CaseT{
int n; cin >> n;
string a, b; cin >> a >> b;
if (a[0] != b[0] || a[n - 1] != b[n - 1]) {
cout << -1 << endl;
continue;
}
function<vi(string)> get = [&](string s)->vi {
vi res;
for (int i = 0; i < n - 1; i++)
if (s[i] != s[i + 1]) res.push_back(i);
return res;
};
vi posa = get(a), posb = get(b);
if (posa.size() != posb.size()) {
cout << -1 << endl;
continue;
}
ll ans = 0;
for (int i = 0; i < posa.size(); i++) ans += abs(posa[i] - posb[i]);
cout << ans << endl;
}
}
33.1 生成函数
生成函数又称母函数,是一种形式幂级数,其每一项的系数可提供关于序列的信息.
生成函数有形式 F ( x ) = ∑ n a n k n ( x ) \displaystyle F(x)=\sum_n a_nk_n(x) F(x)=n∑ankn(x),其中 k n ( x ) k_n(x) kn(x)称为核函数.用 [ k n ( x ) ] F ( x ) [k_n(x)]F(x) [kn(x)]F(x)表示 F ( x ) F(x) F(x)第 n n n项的核函数对应的系数,即 a n a_n an.
不同的核函数导出不同的生成函数,如:①普通生成函数 k n ( x ) = x n k_n(x)=x^n kn(x)=xn;②指数生成函数 k n ( x ) = x n n ! k_n(x)=\dfrac{x^n}{n!} kn(x)=n!xn;③Dirichlet生成函数 k n ( x ) = 1 n x k_n(x)=\dfrac{1}{n^x} kn(x)=nx1.
33.1.1 普通生成函数
有穷或无穷序列 a a a的普通生成函数(Ordinary Generating Function,OGF)定义为形式幂级数 F ( x ) = ∑ n a n x n \displaystyle F(x)=\sum_n a_nx^n F(x)=n∑anxn.
若 a a a有通项,则其普通生成函数的系数即通项.如:
①序列 a : 1 2 3 a:1\ 2\ 3 a:1 2 3的普通生成函数为 1 + 2 x + 3 x 2 1+2x+3x^2 1+2x+3x2.
②序列 a : 1 1 1 a:1\ 1\ 1 a:1 1 1的普通生成函数为 ∑ n ≥ 0 x n \displaystyle\sum_{n\geq 0}x^n n≥0∑xn.
③序列 a : 1 2 4 8 16 a:1\ 2\ 4\ 8\ 16 a:1 2 4 8 16的普通生辰函数为 ∑ n ≥ 0 2 n x n \displaystyle \sum_{n\geq 0}2^nx^n n≥0∑2nxn.
设序列 a , b a,b a,b的普通生成函数分别为 F ( x ) F(x) F(x)和 G ( x ) G(x) G(x).
① F ( x ) ± G ( x ) = ∑ n ( a n + b n ) x n \displaystyle F(x)\pm G(x)=\sum_n (a_n+b_n)x^n F(x)±G(x)=n∑(an+bn)xn,即 F ( x ) ± G ( x ) F(x)\pm G(x) F(x)±G(x)是序列 ( a n + b n ) (a_n+b_n) (an+bn)的普通生成函数.
② F ( x ) G ( x ) = ∑ n x n ∑ i = 0 n a i b n − i \displaystyle F(x)G(x)=\sum_n x^n\sum_{i=0}^n a_i b_{n-i} F(x)G(x)=n∑xni=0∑naibn−i,即 F ( x ) G ( x ) F(x)G(x) F(x)G(x)是序列 ( ∑ i = 0 n a i b n − i ) \displaystyle \left(\sum_{i=0}^n a_ib_{n-i}\right) (i=0∑naibn−i)的普通生成函数.
实际应用中不会一直保留形式幂级数的形式,而会转化为封闭形式以便更好地化简.
①序列 a : 1 , 1 , 1 , ⋯ a:1,1,1,\cdots a:1,1,1,⋯的生成函数 F ( x ) = ∑ n ≥ 0 x n \displaystyle F(x)=\sum_{n\geq 0}x^n F(x)=n≥0∑xn.
显然 x F ( x ) + 1 = F ( x ) xF(x)+1=F(x) xF(x)+1=F(x),解得 F ( x ) = 1 1 − x F(x)=\dfrac{1}{1-x} F(x)=1−x1,这是 ∑ n ≥ 0 x n \displaystyle\sum_{n\geq 0}x^n n≥0∑xn的封闭形式.
②序列 a : 1 , p , p 2 , ⋯ a:1,p,p^2,\cdots a:1,p,p2,⋯的生成函数 F ( x ) = ∑ n ≥ 0 p n x n \displaystyle F(x)=\sum_{n\geq 0}p^n x^n F(x)=n≥0∑pnxn.
显然 p x F ( x ) + 1 = F ( x ) pxF(x)+1=F(x) pxF(x)+1=F(x),解得 F ( x ) = 1 1 − p x F(x)=\dfrac{1}{1-px} F(x)=1−px1.等比级数的展开形式和封闭形式是常用的变换手段.
③序列 a : 0 , 1 , 1 , 1 , ⋯ a:0,1,1,1,\cdots a:0,1,1,1,⋯的生成函数 F ( x ) = ∑ n ≥ 1 x n = x 1 − x \displaystyle F(x)=\sum_{n\geq 1}x^n=\dfrac{x}{1-x} F(x)=n≥1∑xn=1−xx.
④序列 a : 1 , 0 , 1 , 0 , 1 , ⋯ a:1,0,1,0,1,\cdots a:1,0,1,0,1,⋯的生成函数 F ( x ) = ∑ n ≥ 0 x 2 n = ∑ n ≥ 0 ( x 2 ) n = 1 1 − x 2 \displaystyle F(x)=\sum_{n\geq 0}x^{2n}=\sum_{n\geq 0}(x^2)^n=\dfrac{1}{1-x^2} F(x)=n≥0∑x2n=n≥0∑(x2)n=1−x21.
⑤序列 a : 1 , 2 , 3 , 4 , ⋯ a:1,2,3,4,\cdots a:1,2,3,4,⋯的生成函数 F ( x ) = ∑ n ≥ 0 ( n + 1 ) x n = ∑ n ≥ 1 n x n − 1 = ∑ n ≥ 0 ( x n ) ′ = ( 1 1 − x ) ′ = 1 ( 1 − x ) 2 \displaystyle F(x)=\sum_{n\geq 0}(n+1)x^n=\sum_{n\geq 1}nx^{n-1}=\sum_{n\geq 0}(x^n)'=\left(\dfrac{1}{1-x}\right)'=\dfrac{1}{(1-x)^2} F(x)=n≥0∑(n+1)xn=n≥1∑nxn−1=n≥0∑(xn)′=(1−x1)′=(1−x)21.
⑥序列 a n = ( m n ) ( n ≥ 0 , m = C o n s t . ) a_n=\begin{pmatrix}m \\ n\end{pmatrix}\ \ (n\geq 0,m=\mathrm{Const.}) an=(mn) (n≥0,m=Const.)的生成函数 F ( x ) = ∑ n ≥ 0 ( m n ) x n = ( 1 + x ) m \displaystyle F(x)=\sum_{n\geq 0}\begin{pmatrix}m \\ n\end{pmatrix}x^n=(1+x)^m F(x)=n≥0∑(mn)xn=(1+x)m.
⑦序列 a n = ( n + m n ) ( n ≥ 0 , m = C o n s t . ) a_n=\begin{pmatrix}n+m \\ n\end{pmatrix}\ \ (n\geq 0,m=\mathrm{Const.}) an=(n+mn) (n≥0,m=Const.)的生成函数 F ( x ) = ∑ n ≥ 0 ( n + m n ) x n = 1 ( 1 − x ) m + 1 \displaystyle F(x)=\sum_{n\geq 0}\begin{pmatrix}n+m \\ n\end{pmatrix}x^n=\dfrac{1}{(1-x)^{m+1}} F(x)=n≥0∑(n+mn)xn=(1−x)m+11.
[证] 数归. m = 0 m=0 m=0时, F ( x ) = 1 1 − x F(x)=\dfrac{1}{1-x} F(x)=1−x1.
m > 0 m>0 m>0时, 1 ( 1 − x ) m + 1 = 1 ( 1 − x ) m ⋅ 1 1 − x = [ ∑ n ≥ 0 ( n + m − 1 n ) x n ] ( ∑ n ≥ 0 x n ) \displaystyle \dfrac{1}{(1-x)^{m+1}}=\dfrac{1}{(1-x)^m}\cdot\dfrac{1}{1-x}=\left[\sum_{n\geq 0}\begin{pmatrix}n+m-1 \\ n\end{pmatrix}x^n\right]\left(\sum_{n\geq 0}x^n\right) (1−x)m+11=(1−x)m1⋅1−x1=[n≥0∑(n+m−1n)xn](n≥0∑xn)
= ∑ n ≥ 0 x n ∑ i = 0 n ( m + i − 1 i ) = ∑ n ≥ 0 ( n + m n ) x n \displaystyle =\sum_{n\geq 0}x^n \sum_{i=0}^n \begin{pmatrix}m+i-1 \\ i\end{pmatrix}=\sum_{n\geq 0}\begin{pmatrix}n+m \\ n\end{pmatrix}x^n =n≥0∑xni=0∑n(m+i−1i)=n≥0∑(n+mn)xn. *第三个等号先枚举 x n x^n xn,再枚举其系数
[Fibonacci数列的生成函数]
Fibonacci数列 a 0 = 0 , a 1 = 1 , a n = a n − 1 + a n − 2 ( n ≥ 1 ) a_0=0,a_1=1,a_n=a_{n-1}+a_{n-2}\ \ (n\geq 1) a0=0,a1=1,an=an−1+an−2 (n≥1).
设其普通生成函数为 F ( x ) F(x) F(x),则 F ( x ) = ∑ n ≥ 0 a n x n , x F ( x ) = ∑ n ≥ 1 a n − 1 x n , x 2 F ( x ) = ∑ n ≥ 1 a n − 2 x n \displaystyle F(x)=\sum_{n\geq 0}a_nx^n,xF(x)=\sum_{n\geq 1}a_{n-1}x^n,x^2F(x)=\sum_{n\geq 1}a_{n-2}x^n F(x)=n≥0∑anxn,xF(x)=n≥1∑an−1xn,x2F(x)=n≥1∑an−2xn.
注意到 x F ( x ) + x 2 F ( x ) = ∑ n ≥ 2 ( a n − 1 + a n − 2 ) x n + a 0 x = ∑ n ≥ 2 a n x n + a 0 x \displaystyle xF(x)+x^2F(x)=\sum_{n\geq 2}(a_{n-1}+a_{n-2})x^n+a_0x=\sum_{n\geq 2}a_nx^n+a_0x xF(x)+x2F(x)=n≥2∑(an−1+an−2)xn+a0x=n≥2∑anxn+a0x,
则 F ( x ) = x F ( x ) + x 2 F ( x ) − a 0 x + a 1 x + a 0 F(x)=xF(x)+x^2F(x)-a_0x+a_1x+a_0 F(x)=xF(x)+x2F(x)−a0x+a1x+a0,解得 F ( x ) = x 1 − x − x 2 F(x)=\dfrac{x}{1-x-x^2} F(x)=1−x−x2x,这是Fibonacci数列的一个封闭形式.
下面求其展开形式:
[解1] F ( x ) = x 1 − ( x + x 2 ) = ∑ n ≥ 0 ( x + x 2 ) n = ∑ n ≥ 0 ∑ i = 0 n ( n i ) x 2 i x n − i \displaystyle F(x)=\dfrac{x}{1-(x+x^2)}=\sum_{n\geq 0}(x+x^2)^n=\sum_{n\geq 0}\sum_{i=0}^n \begin{pmatrix}n \\ i\end{pmatrix}x^{2i}x^{n-i} F(x)=1−(x+x2)x=n≥0∑(x+x2)n=n≥0∑i=0∑n(ni)x2ixn−i
= ∑ n ≥ 0 ∑ i = 0 n ( n i ) x n + i = ∑ n ≥ 0 x n ∑ i = 0 n ( n − i i ) \displaystyle =\sum_{n\geq 0}\sum_{i=0}^n \begin{pmatrix}n \\ i\end{pmatrix}x^{n+i}=\sum_{n\geq 0}x^n\sum_{i=0}^n \begin{pmatrix}n-i \\ i\end{pmatrix} =n≥0∑i=0∑n(ni)xn+i=n≥0∑xni=0∑n(n−ii).
[解2] 设 x 1 − x − x 2 = A 1 − a x + B 1 − b x = A − A b x + B − a B x ( 1 − a x ) ( 1 − b x ) \dfrac{x}{1-x-x^2}=\dfrac{A}{1-ax}+\dfrac{B}{1-bx}=\dfrac{A-Abx+B-aBx}{(1-ax)(1-bx)} 1−x−x2x=1−axA+1−bxB=(1−ax)(1−bx)A−Abx+B−aBx,则 { A + B = 0 − A b − a B = 1 a + b = 1 a b = − 1 \begin{cases}A+B=0 \\ -Ab-aB=1 \\ a+b=1 \\ ab=-1\end{cases} ⎩ ⎨ ⎧A+B=0−Ab−aB=1a+b=1ab=−1,解得 { A = 1 5 B = − 1 5 C = 1 + 5 2 D = 1 − 5 2 \begin{cases}A=\dfrac{1}{\sqrt{5}} \\ B=-\dfrac{1}{\sqrt{5}} \\ C=\dfrac{1+\sqrt{5}}{2} \\ D=\dfrac{1-\sqrt{5}}{2}\end{cases} ⎩ ⎨ ⎧A=51B=−51C=21+5D=21−5,
故 x 1 − x − x 2 = ∑ n ≥ 0 x n 1 5 [ ( 1 + 5 2 ) n − ( 1 − 5 2 ) n ] \displaystyle \dfrac{x}{1-x-x^2}=\sum_{n\geq 0}x^n \dfrac{1}{\sqrt{5}}\left[\left(\dfrac{1+\sqrt{5}}{2}\right)^n-\left(\dfrac{1-\sqrt{5}}{2}\right)^n\right] 1−x−x2x=n≥0∑xn51[(21+5)n−(21−5)n],这是Fibonacci数列的l另一个封闭形式.
对多项式 P ( x ) , Q ( x ) P(x),Q(x) P(x),Q(x),可用类似的方法求出生成函数 P ( x ) Q ( x ) \dfrac{P(x)}{Q(x)} Q(x)P(x)的展开式.
如求 G ( x ) = 1 ( 1 − x ) ( 1 − 2 x ) 2 G(x)=\dfrac{1}{(1-x)(1-2x)^2} G(x)=(1−x)(1−2x)21的展开式,因 G ( x ) = 1 1 − x + − 2 1 − 2 x + 2 ( 1 − 2 x ) 2 G(x)=\dfrac{1}{1-x}+\dfrac{-2}{1-2x}+\dfrac{2}{(1-2x)^2} G(x)=1−x1+1−2x−2+(1−2x)22,
则 [ x n ] G ( x ) = 1 − 2 n + 1 + ( n + 1 ) ⋅ 2 n + 1 [x^n]G(x)=1-2^{n+1}+(n+1)\cdot 2^{n+1} [xn]G(x)=1−2n+1+(n+1)⋅2n+1.
[Newton二项式定理]
重定义组合数 ( r k ) = r k ‾ k ! ( r ∈ C , k ∈ N ) \begin{pmatrix}r \\ k\end{pmatrix}=\dfrac{r^{\underline{k}}}{k!}\ \ (r\in\mathbb{C},k\in\mathbb{N}) (rk)=k!rk (r∈C,k∈N),则对 ∀ α ∈ C \forall \alpha\in\mathbb{C} ∀α∈C,有 ( 1 + x ) α = ∑ n ≥ 0 ( α n ) x n \displaystyle (1+x)^\alpha=\sum_{n\geq 0}\begin{pmatrix}\alpha \\ n\end{pmatrix}x^n (1+x)α=n≥0∑(αn)xn.
二项式定理是Newton二项式定理的特例.
[Catalan数的生成函数]
Catalan数 H 0 = H 1 = 1 , H n = ∑ i = 0 n − 1 H i H n − i − 1 ( n ≥ 2 ) \displaystyle H_0=H_1=1,H_n=\sum_{i=0}^{n-1} H_iH_{n-i-1}\ \ (n\geq 2) H0=H1=1,Hn=i=0∑n−1HiHn−i−1 (n≥2),递推式有卷积的形式.
设其普通生成函数为 H ( x ) H(x) H(x),则 H ( x ) = ∑ n ≥ 0 H n x n = 1 + ∑ n ≥ 1 ∑ i = 0 n − 1 H i x i H n − i − 1 x n − i − 1 x \displaystyle H(x)=\sum_{n\geq0}H_nx^n=1+\sum_{n\geq 1}\sum_{i=0}^{n-1} H_ix^i H_{n-i-1}x^{n-i-1}x H(x)=n≥0∑Hnxn=1+n≥1∑i=0∑n−1HixiHn−i−1xn−i−1x
= 1 + x ∑ i ≥ 0 H i x i ∑ n ≥ 0 H n x n = 1 + x H 2 ( x ) \displaystyle =1+x\sum_{i\geq 0}H_ix^i\sum_{n\geq 0}H_nx^n=1+xH^2(x) =1+xi≥0∑Hixin≥0∑Hnxn=1+xH2(x),解得 H ( x ) = 1 ± 1 − 4 x 2 x = 2 1 ∓ 1 − 4 x H(x)=\dfrac{1\pm \sqrt{1-4x}}{2x}=\dfrac{2}{1\mp \sqrt{1-4x}} H(x)=2x1±1−4x=1∓1−4x2.
代入 x = 0 x=0 x=0,得到 H ( x ) H(x) H(x)的常数项 H 0 H_0 H0,检验得 H ( x ) = 2 1 + 1 − 4 x H(x)=\dfrac{2}{1+\sqrt{1-4x}} H(x)=1+1−4x2满足.
故Catalan数的生成函数的封闭形式为 H ( x ) = 1 − 1 − 4 x 2 x H(x)=\dfrac{1-\sqrt{1-4x}}{2x} H(x)=2x1−1−4x.
下面将其展开.先展开 1 − 4 x \sqrt{1-4x} 1−4x.
因 1 − 4 x = ( 1 − 4 x ) 1 2 = ∑ n ≥ 0 ( 1 2 n ) ( − 4 x ) n = 1 + ∑ n ≥ 1 ( 1 2 ) n ‾ n ! ( − 4 x ) n \displaystyle \sqrt{1-4x}=(1-4x)^\frac{1}{2}=\sum_{n\geq 0}\begin{pmatrix}\dfrac{1}{2} \\ n\end{pmatrix}(-4x)^n=1+\sum_{n\geq 1}\dfrac{\left(\dfrac{1}{2}\right)^{\underline{n}}}{n!}(-4x)^n 1−4x=(1−4x)21=n≥0∑(21n)(−4x)n=1+n≥1∑n!(21)n(−4x)n,
注意到 ( 1 2 ) n ‾ = 1 2 ⋅ − 1 2 ⋅ − 3 2 ⋯ − ( 2 n − 3 ) 2 = ( − 1 ) n − 1 ( 2 n − 3 ) ! ! 2 n \left(\dfrac{1}{2}\right)^{\underline{n}}=\dfrac{1}{2}\cdot \dfrac{-1}{2}\cdot\dfrac{-3}{2}\cdots\dfrac{-(2n-3)}{2}=\dfrac{(-1)^{n-1}(2n-3)!!}{2^n} (21)n=21⋅2−1⋅2−3⋯2−(2n−3)=2n(−1)n−1(2n−3)!!
= ( − 1 ) n − 1 ( 2 n − 2 ) ! 2 n ( 2 n − 2 ) ! ! = ( − 1 ) n − 1 ( 2 n − 2 ) ! 2 2 n − 1 ( n − 1 ) ! =\dfrac{(-1)^{n-1}(2n-2)!}{2^n(2n-2)!!}=\dfrac{(-1)^{n-1}(2n-2)!}{2^{2n-1}(n-1)!} =2n(2n−2)!!(−1)n−1(2n−2)!=22n−1(n−1)!(−1)n−1(2n−2)!,
则 1 − 4 x = 1 + ∑ n ≥ 1 ( − 1 ) n − 1 ( 2 n − 2 ) ! 2 2 n − 1 ( n − 1 ) ! n ! ( − 4 x ) n = 1 − ∑ n ≥ 1 ( 2 n − 2 ) ! ( n − 1 ) ! n ! 2 x n = 1 − ∑ n ≥ 1 ( 2 n − 1 n ) 2 2 n − 1 x n \displaystyle \sqrt{1-4x}=1+\sum_{n\geq 1}\dfrac{(-1)^{n-1}(2n-2)!}{2^{2n-1}(n-1)!n!}(-4x)^n=1-\sum_{n\geq 1}\dfrac{(2n-2)!}{(n-1)!n!}2x^n=1-\sum_{n\geq 1}\begin{pmatrix}2n-1 \\ n\end{pmatrix}\dfrac{2}{2n-1}x^n 1−4x=1+n≥1∑22n−1(n−1)!n!(−1)n−1(2n−2)!(−4x)n=1−n≥1∑(n−1)!n!(2n−2)!2xn=1−n≥1∑(2n−1n)2n−12xn.
故 H ( x ) = 1 2 x ∑ n ≥ 1 ( 2 n − 1 n ) 2 2 n − 1 x n = ∑ n ≥ 1 ( 2 n − 1 n ) 1 2 n − 1 x n − 1 \displaystyle H(x)=\dfrac{1}{2x}\sum_{n\geq 1}\begin{pmatrix}2n-1 \\ n\end{pmatrix}\dfrac{2}{2n-1}x^n=\sum_{n\geq 1}\begin{pmatrix}2n-1 \\ n\end{pmatrix}\dfrac{1}{2n-1}x^{n-1} H(x)=2x1n≥1∑(2n−1n)2n−12xn=n≥1∑(2n−1n)2n−11xn−1
= ∑ n ≥ 0 ( 2 n + 1 n + 1 ) 1 2 n + 1 x n = ∑ n ≥ 0 ( 2 n n ) 1 n + 1 x n \displaystyle =\sum_{n\geq 0}\begin{pmatrix}2n+1 \\ n+1\end{pmatrix}\dfrac{1}{2n+1}x^n=\sum_{n\geq 0}\begin{pmatrix}2n \\ n\end{pmatrix}\dfrac{1}{n+1}x^n =n≥0∑(2n+1n+1)2n+11xn=n≥0∑(2nn)n+11xn,即 H n = 1 n + 1 ( 2 n n ) H_n=\dfrac{1}{n+1}\begin{pmatrix}2n \\ n\end{pmatrix} Hn=n+11(2nn).
33.1.1.1 食物
原题指路:https://darkbzoj.cc/problem/3028
题意
有如下七种食物的选择要求(假设都以"个"为单位):①汉堡:偶数个;②可乐: 0 0 0个或 1 1 1个;③鸡腿: 0 0 0个、 1 1 1个或 2 2 2个;④蜜桃:奇数个;⑤鸡块: 4 4 4的倍数个;⑥包子: 0 0 0个、 1 1 1个、 2 2 2个或 3 3 3个;⑦烤肉:不超过 1 1 1个;⑧面包: 3 3 3的倍数个.
输入整数 n ( 1 ≤ n ≤ 1 e 500 ) n\ \ (1\leq n\leq 1\mathrm{e}500) n (1≤n≤1e500),问食物选的个数之和为 n n n的方案数,答案对 10007 10007 10007取模.
思路
对每种食物,设 a n a_n an表示该种食物选 n n n个的方案数,并求出其生成函数.两种或多种食物共选 n n n个的方案数的生成函数是每种食物的生成函数的卷积,故只需分别求出每种食物的方案数的生成函数,将它们相乘即可.
① ∑ n ≥ 0 x 2 n = 1 1 − x 2 \displaystyle\sum_{n\geq 0}x^{2n}=\dfrac{1}{1-x^2} n≥0∑x2n=1−x21;② 1 + x 1+x 1+x;③ 1 + x + x 2 = 1 − x 3 1 − x 1+x+x^2=\dfrac{1-x^3}{1-x} 1+x+x2=1−x1−x3;④ ∑ n ≥ 1 x 2 n − 1 = x 1 − x 2 \displaystyle\sum_{n\geq 1}x^{2n-1}=\dfrac{x}{1-x^2} n≥1∑x2n−1=1−x2x;
⑤ ∑ n ≥ 0 x 4 n = 1 1 − x 4 \displaystyle\sum_{n\geq 0}x^{4n}=\dfrac{1}{1-x^4} n≥0∑x4n=1−x41;⑥ 1 + x + x 2 + x 3 = 1 − x 4 1 − x 1+x+x^2+x^3=\dfrac{1-x^4}{1-x} 1+x+x2+x3=1−x1−x4;⑦ 1 + x 1+x 1+x;⑧ ∑ n ≥ 0 x 3 n = 1 1 − x 3 \displaystyle\sum_{n\geq 0}x^{3n}=\dfrac{1}{1-x^3} n≥0∑x3n=1−x31.
全部相乘即答案的生成函数 F ( x ) = ( 1 + x ) ( 1 − x 3 ) x ( 1 − x 4 ) ( 1 + x ) ( 1 − x 2 ) ( 1 − x ) ( 1 − x 2 ) ( 1 − x 4 ) ( 1 − x ) ( 1 − x 3 ) = x ( 1 − x ) 4 F(x)=\dfrac{(1+x)(1-x^3)x(1-x^4)(1+x)}{(1-x^2)(1-x)(1-x^2)(1-x^4)(1-x)(1-x^3)}=\dfrac{x}{(1-x)^4} F(x)=(1−x2)(1−x)(1−x2)(1−x4)(1−x)(1−x3)(1+x)(1−x3)x(1−x4)(1+x)=(1−x)4x.
注意到 ∑ n ≥ 0 ( n + m n ) x n = 1 ( 1 − x ) m + 1 \displaystyle \sum_{n\geq 0}\begin{pmatrix}n+m \\ n\end{pmatrix}x^n=\dfrac{1}{(1-x)^{m+1}} n≥0∑(n+mn)xn=(1−x)m+11,则 x ( 1 − x ) m + 1 = ∑ n ≥ 0 ( n + m n ) x n + 1 = ∑ n ≥ 1 ( n + m − 1 n − 1 ) x n \displaystyle \dfrac{x}{(1-x)^{m+1}}=\sum_{n\geq 0}\begin{pmatrix}n+m \\ n\end{pmatrix}x^{n+1}=\sum_{n\geq 1}\begin{pmatrix}n+m-1 \\ n-1\end{pmatrix}x^n (1−x)m+1x=n≥0∑(n+mn)xn+1=n≥1∑(n+m−1n−1)xn.
取 m = 3 m=3 m=3,则 F ( x ) = ∑ n ≥ 1 ( n + 2 n − 1 ) x n \displaystyle F(x)=\sum_{n\geq 1}\begin{pmatrix}n+2 \\ n-1\end{pmatrix}x^n F(x)=n≥1∑(n+2n−1)xn.故 a n s = ( n + 2 n − 1 ) = ( n + 2 3 ) = n ( n + 1 ) ( n + 2 ) 6 ans=\begin{pmatrix}n+2 \\ n-1\end{pmatrix}=\begin{pmatrix}n+2 \\ 3\end{pmatrix}=\dfrac{n(n+1)(n+2)}{6} ans=(n+2n−1)=(n+23)=6n(n+1)(n+2).
代码
const int MOD = 10007;
int main() {
function<int(void)> input = []()->int {
int x = 0;
int sgn = 1;
char ch = getchar();
while (ch < '0' || ch > '9') {
if (ch == '-') sgn = -1;
ch = getchar();
}
while (ch >= '0' && ch <= '9') {
x = (x * 10 + ch - '0') % MOD;
ch = getchar();
}
x *= sgn;
return x;
};
int n = input();
int inv6 = qpow(6, MOD - 2, MOD);
int ans = (ll)n * (n + 1) % MOD * (n + 2) % MOD * inv6 % MOD;
cout << ans << endl;
}