垃圾ACMer的暑假训练220716

垃圾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 12n 2 n 2n 2n个人拍照,其中第 i    ( 1 ≤ i ≤ 2 n ) i\ \ (1\leq i\leq 2n) i  (1i2n)个人的身高为 h i h_i hi.现 2 n 2n 2n个人排成两行,每行 n n n个人,要求后一行的第 j    ( 1 ≤ j ≤ n ) j\ \ (1\leq j\leq n) j  (1jn)个人至少比前一行的第 j j j个人高 x x x.问是否能做到.

t    ( 1 ≤ t ≤ 100 ) t\ \ (1\leq t\leq 100) t  (1t100)组测试数据.每组测试数据第一行输入整数 n , x    ( 1 ≤ n ≤ 100 , 1 ≤ x ≤ 1000 ) n,x\ \ (1\leq n\leq 100,1\leq x\leq 1000) n,x  (1n100,1x1000).第二行输入 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  (1hi1000),分别表示每个人的身高.

对每组测试数据,若能做到,输出"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+ihix  (1in).

[] 注意到 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+ihix.

代码
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,,aj1>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==an1=0.

t    ( 1 ≤ t ≤ 1 e 4 ) t\ \ (1\leq t\leq 1\mathrm{e}4) t  (1t1e4)组测试数据.每组测试数据第一行输入整数 n    ( 2 ≤ n ≤ 2 e 5 ) n\ \ (2\leq n\leq 2\mathrm{e}5) n  (2n2e5),表示序列长度.第二行输入 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  (0ai1e9).数据保证所有测试数据的 n n n之和不超过 2 e 5 2\mathrm{e}5 2e5.

对每组测试数据,输出最小步数.数据保证有解.

思路I

观察样例猜测:有解的序列的前 ( n − 1 ) (n-1) (n1)中非零数的左右都是 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) (x1)步变为 0 0 0,且从第一个非零数开始到第 ( n − 1 ) (n-1) (n1)个数的位置在途中都会出现 1 1 1,故还需 ( n − i d x − 1 ) (n-idx-1) (nidx1)步.

代码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,,an1 0 0 0的个数,则 a n s = ( a 1 + ⋯ + a n − 1 ) + k ans=(a_1+\cdots+a_{n-1})+k ans=(a1++an1)+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,,an1中的所有 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++an1)次操作将 a 1 , ⋯   , a n − 1 a_1,\cdots,a_{n-1} a1,,an1变为 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++an1)减少 1 1 1.

②若操作的 j ≠ n j\neq n j=n,则它不会减少 ( a 1 + ⋯ + a n − 1 ) (a_1+\cdots+a_{n-1}) (a1++an1),但至多会让 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[lr]接到 s s s的后面.操作结束后有 q q q个询问,每个询问给定一个数 k k k,输出当前字符串的第 k k k个字符.

t    ( 1 ≤ t ≤ 1000 ) t\ \ (1\leq t\leq 1000) t  (1t1000)组测试数据.每组测试数据第一行输入三个整数 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  (1n2e5,1c40,1q1e4).第二行输入长度为 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]  (1lr1e18),表示要操作的区间,数据保证 r r r不超过当前字符串的长度.接下来 q q q行每行输入一个整数 k    ( 1 ≤ k ≤ 1 e 18 ) k\ \ (1\leq k\leq 1\mathrm{e}18) k  (1k1e18),表示询问的下标,数据保证 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) (kdiff)个字符相同,递推到初始字符串的区间即可.时间复杂度 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=s1s2sn.现可进行操作:取一个下标 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,n1] s.t. si1=si+1,反转 s i s_i si的值.

t    ( 1 ≤ t ≤ 1 e 4 ) t\ \ (1\leq t\leq 1\mathrm{e}4) t  (1t1e4)组测试数据.每组测试数据第一行输入一个整数 n    ( 3 ≤ n ≤ 2 e 5 ) n\ \ (3\leq n\leq 2\mathrm{e}5) n  (3n2e5),表示二进制串的长度.第二行和第三行分别输入两长度为 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[n1]=t[n1],则无解.

对长度为 n n n的二进制串 s s s,构造长度为 ( n − 1 ) (n-1) (n1)的二进制串 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)(sn1 xor sn),则对 s s s的操作即交换 s ‾ \overline s s相邻的两bit.

s = 000101 → t = 010011 s=000101\rightarrow t=010011 s=000101t=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=a1b1+a2b2++akbk,这是因为最优策略中 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)=nankn(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)=nanxn.

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 n0xn.

③序列 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 n02nxn.

设序列 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)=nxni=0naibni,即 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=0naibni)的普通生成函数.

实际应用中不会一直保留形式幂级数的形式,而会转化为封闭形式以便更好地化简.

①序列 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)=n0xn.

​ 显然 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)=1x1,这是 ∑ n ≥ 0 x n \displaystyle\sum_{n\geq 0}x^n n0xn的封闭形式.

②序列 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)=n0pnxn.

​ 显然 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)=1px1.等比级数的展开形式和封闭形式是常用的变换手段.

③序列 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)=n1xn=1xx.

④序列 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)=n0x2n=n0(x2)n=1x21.

⑤序列 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)=n0(n+1)xn=n1nxn1=n0(xn)=(1x1)=(1x)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)  (n0,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)=n0(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)  (n0,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)=n0(n+mn)xn=(1x)m+11.

[] 数归. m = 0 m=0 m=0时, F ( x ) = 1 1 − x F(x)=\dfrac{1}{1-x} F(x)=1x1.

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) (1x)m+11=(1x)m11x1=[n0(n+m1n)xn](n0xn)

= ∑ 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 =n0xni=0n(m+i1i)=n0(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=an1+an2  (n1).

设其普通生成函数为 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)=n0anxn,xF(x)=n1an1xn,x2F(x)=n1an2xn.

注意到 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)=n2(an1+an2)xn+a0x=n2anxn+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)=1xx2x,这是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=n0(x+x2)n=n0i=0n(ni)x2ixni

= ∑ 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} =n0i=0n(ni)xn+i=n0xni=0n(nii).

[解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)} 1xx2x=1axA+1bxB=(1ax)(1bx)AAbx+BaBx,则 { 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=0AbaB=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=5 1B=5 1C=21+5 D=215 ,

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] 1xx2x=n0xn5 1[(21+5 )n(215 )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)=(1x)(12x)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)=1x1+12x2+(12x)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)=12n+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  (rC,kN),则对 ∀ α ∈ 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)α=n0(α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=0n1HiHni1  (n2),递推式有卷积的形式.

设其普通生成函数为 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)=n0Hnxn=1+n1i=0n1HixiHni1xni1x

= 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+xi0Hixin0Hnxn=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±14x =114x 2.

代入 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+14x 2满足.

故Catalan数的生成函数的封闭形式为 H ( x ) = 1 − 1 − 4 x 2 x H(x)=\dfrac{1-\sqrt{1-4x}}{2x} H(x)=2x114x .

下面将其展开.先展开 1 − 4 x \sqrt{1-4x} 14x .

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 14x =(14x)21=n0(21n)(4x)n=1+n1n!(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=2121232(2n3)=2n(1)n1(2n3)!!

= ( − 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(2n2)!!(1)n1(2n2)!=22n1(n1)!(1)n1(2n2)!,

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 14x =1+n122n1(n1)!n!(1)n1(2n2)!(4x)n=1n1(n1)!n!(2n2)!2xn=1n1(2n1n)2n12xn.

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)=2x1n1(2n1n)2n12xn=n1(2n1n)2n11xn1

= ∑ 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 =n0(2n+1n+1)2n+11xn=n0(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  (1n1e500),问食物选的个数之和为 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} n0x2n=1x21;② 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=1x1x3;④ ∑ n ≥ 1 x 2 n − 1 = x 1 − x 2 \displaystyle\sum_{n\geq 1}x^{2n-1}=\dfrac{x}{1-x^2} n1x2n1=1x2x;

∑ n ≥ 0 x 4 n = 1 1 − x 4 \displaystyle\sum_{n\geq 0}x^{4n}=\dfrac{1}{1-x^4} n0x4n=1x41;⑥ 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=1x1x4;⑦ 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} n0x3n=1x31.

全部相乘即答案的生成函数 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)=(1x2)(1x)(1x2)(1x4)(1x)(1x3)(1+x)(1x3)x(1x4)(1+x)=(1x)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}} n0(n+mn)xn=(1x)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 (1x)m+1x=n0(n+mn)xn+1=n1(n+m1n1)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)=n1(n+2n1)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+2n1)=(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;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值