m = 2 m=2 m = 2 
如果一个序列存在i < j i<j i < j a i > a j a_{i}>a_{j} a i  > a j  m = 2 m=2 m = 2 
否则,这个序列单调不降,其任意一个子序列也单调不降,不存在 derangement 的子序列。
复杂度O ( n 2 ) \mathcal{O}(n^{2}) O ( n 2 ) O ( n ) \mathcal{O}(n) O ( n ) 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 auto  solve = [&] {	int  n; 	cin >> n; 	vector<int > a (n)  ; 	for  (int  i = 0 ; i < n; i++) { 		cin >> a[i]; 	} 	for  (int  i = 0 ; i < n; i++) { 		for  (int  j = i + 1 ; j < n; j++) { 			if  (a[i] > a[j]) { 				cout << "YES"  << endl; 				cout << 2  << endl; 				cout << a[i] << ' '  << a[j] << endl; 				return ; 			} 		} 	} 	cout << "NO"  << endl; }; 
为影响最小,选择i + 1 = j i+1=j i + 1 = j i i i 
复杂度O ( n ) \mathcal{O}(n) O ( n ) 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 auto  solve = [&] {	int  n; 	cin >> n; 	vector<int > a (n)  ; 	for  (int  i = 0 ; i < n; i++) { 		cin >> a[i]; 	} 	ll res = inf; 	ll sum = 0 ; 	int  minn = inf;  	for  (int  i = 0 ; i < n; i++) { 		if  (i < n - 1 ) { 			res = min (res, sum + min (minn, a[i] + a[i + 1 ])); 		} 		if  (a[i] < minn) { 			minn = a[i]; 		} 		sum += minn; 	} 	res = min (res, sum); 	cout << res << endl;             }; 
如果某个b i − 1 ∤ b i b_{i-1}\nmid b_{i} b i − 1  ∤ b i  x : = b i − 1 gcd  ( b i − 1 , b i ) x := \dfrac{b_{i-1}}{\gcd(b_{i-1}, b_{i})} x : = g cd( b i − 1  , b i  ) b i − 1   b i − 1 b_{i-1} b i − 1  x x x 
如果有多个b i − 1 ∤ b i b_{i-1}\nmid b_{i} b i − 1  ∤ b i  x x x b i − 1 gcd  ( b i − 1 , b i ) \dfrac{b_{i-1}}{\gcd(b_{i-1}, b_{i})} g cd( b i − 1  , b i  ) b i − 1   
每个数只由它后面的数决定,因此倒着循环。
复杂度O ( n log  n ) \mathcal{O}(n\log n) O ( n log  n ) 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 auto  solve = [&] {	int  n; 	cin >> n; 	vector<int > b (n)  ; 	for  (int  i = 0 ; i < n; i++) { 		cin >> b[i]; 	}          	int  x = 1 ; 	for  (int  i = n - 1 ; i > 0 ; i--) { 		if  (b[i] % b[i - 1 ] != 0 ) { 			x = lcm (x, b[i - 1 ] / gcd (b[i - 1 ], b[i])); 			b[i - 1 ] /= x; 		} 	} 	cout << x << endl; }; 
需要几个观察:
数组最后剩下的元素个数⩾ k − 1 \geqslant k-1 ⩾ k − 1 
比整个数组的第k k k w w w 
比w w w 
在 1 的条件下,等于w w w w w w k k k 
现在我们贪心地,
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 auto  solve = [&] {	int  n, k; 	cin >> n >> k; 	vector<int > a (n)  ; 	for  (int  i = 0 ; i < n; i++) { 		cin >> a[i]; 	}          	auto  b = a; 	sort (b.begin (), b.end ()); 	int  w = b[k - 1 ];   	 	vector<int > c; 	int  cnt = 0 ; 	vector<int > d; 	for  (int  i = 0 ; i < n; i++) { 		if  (a[i] < w) { 			c.push_back (a[i]); 			d.push_back (cnt);   			cnt = 0 ; 		} else  if  (a[i] == w) { 			cnt++; 		} 	} 	d.push_back (cnt);   	 	for  (int  i = 0 ; i < d.size (); i++) { 		d[i] = min (d[i], d[d.size () - i - 1 ]);   	} 	 	if  (c != vector (c.rbegin (), c.rend ())) {   		cout << "NO"  << endl; 		return ; 	} 	 	if  (accumulate (d.begin (), d.end (), 0 ) + c.size () < k - 1 ) {   		cout << "NO"  << endl; 		return ; 	} 	cout << "YES"  << endl; }; 
不知道 17 次哪来的,两次足够。 
首先判掉一次的情形。
否则设最中间的那个元素为a i a_{i} a i  D = ∑ j = 1 i − 1 a j \displaystyle D=\sum_{j=1}^{i-1}a_{j} D = j = 1 ∑ i − 1  a j  E = ∑ j = i + 1 n a j \displaystyle E=\sum_{j=i+1}^{n}a_{j} E = j = i + 1 ∑ n  a j  D + a i ⩾ E , D ⩽ a i + E ( 1 ) D+a_{i} \geqslant E,\quad D \leqslant a_{i}+E \quad (1) D + a i  ⩾ E , D ⩽ a i  + E ( 1 ) 
先试试两次行不行,如果可以,就是拆成
{ D 1 + a i 1 = E 1 D 2 = a i 2 + E 2 \begin{cases} D_{1}+a_{i 1}=E_{1} \\ D_{2}=a_{i 2}+E_{2} \end{cases} { D 1  + a i 1  = E 1  D 2  = a i 2  + E 2   
解这个方程能得到a i 1 = E + a i − D 2 , a i 2 = D + a i − E 2 a_{i 1}=\dfrac{E+a_{i}-D}{2}, \quad a_{i 2}=\dfrac{D+a_{i}-E}{2} a i 1  = 2 E + a i  − D  , a i 2  = 2 D + a i  − E  
只需验证是否满足a i 1 ⩽ E 1 ⩽ E , a i 2 ⩽ D 2 ⩽ D a_{i 1} \leqslant E_{1} \leqslant E, \quad a_{i 2} \leqslant D_{2} \leqslant D a i 1  ⩽ E 1  ⩽ E , a i 2  ⩽ D 2  ⩽ D 
其余情况一定有解,随便构造就行,比如可以取
{ 0 + a i 1 = a i 1 D = a i 2 + ( E − a i 1 ) \begin{cases} 0+a_{i 1}=a_{i 1} \\ D=a_{i 2}+(E-a_{i 1}) \end{cases} { 0 + a i 1  = a i 1  D = a i 2  + ( E − a i 1  )  
这样两组。
代码写得有点丑 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 auto  solve = [&] {	int  n; 	cin >> n; 	vector<ll> a (n)  ; 	for  (int  i = 0 ; i < n; i++) { 		cin >> a[i]; 	}          	ll sum = accumulate (a.begin (), a.end (), 0ll ); 	if  (sum % 2  != 0 ) { 		cout << -1  << endl; 		return ; 	} 	ll sum1 = 0 ; 	int  i = 0 ; 	while  (i < n && sum1 < sum / 2 ) { 		sum1 += a[i]; 		i++; 	} 	if  (sum1 == sum / 2 ) { 		cout << 1  << endl; 		for  (int  i = 0 ; i < n; i++) { 			cout << a[i] << " " ; 		} 		cout << endl; 	} else  { 		i--; 		 		ll D = sum1 - a[i]; 		ll E = sum - sum1; 		ll ai1 = (E + a[i] - D) / 2 ; 		ll ai2 = (D + a[i] - E) / 2 ; 		 		if  (E < ai1 || D < ai2) { 			cout << -1  << endl; 			return ; 		} 		 		cout << 2  << endl; 		ll need = D; 		for  (int  j = 0 ; j < i; j++) { 			ll x = min (need, a[j]); 			cout << x << " " ; 			need -= x; 			a[j] -= x; 		} 		cout << ai2 << " " ; 		 		need = E - ai1; 		for  (int  j = i + 1 ; j < n; j++) { 			ll x = min (need, a[j]); 			cout << x << " " ; 			need -= x; 			a[j] -= x; 		} 		cout << endl; 		for  (int  j = 0 ; j < i; j++) { 			cout << 0  << " " ; 		} 		cout << ai1 << " " ; 		 		need = ai1; 		for  (int  j = i + 1 ; j < n; j++) { 			ll x = min (need, a[j]); 			cout << x << " " ; 			need -= x; 		} 		cout << endl; 	} }; 
很容易想到按每一段来 DP,设f i f_{i} f i  i i i f j ,   j < i f_{j},\ j<i f j  ,   j < i O ( n 2 ) \mathcal{O}(n^{2}) O ( n 2 ) 
至于转移系数,F1 的数据范围允许我们枚举s , r s,r s , r 
总复杂度O ( n 4 ) \mathcal{O}(n^{4}) O ( n 4 ) 
这一部分的代码:(还有第二部分) 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 auto  solve = [&] {	int  n, m; 	cin >> n >> m; 	vector adj (n + 1 , vector<int >(n + 1 ))  ; 	while  (m--) { 		int  i, x; 		cin >> i >> x; 		adj[i][x] = 1 ; 	} 	vector<Z> f (n + 1 )  ; 	f[0 ] = 1 ; 	for  (int  i = 1 ; i <= n; i++) { 		for  (int  j = 0 ; j < i; j++) { 			Z sum = 0 ; 			int  s = i - j; 			for  (int  r = 1 ; r <= s; r++) { 				int  pos = j; 				int  num = r - 1 ; 				bool  ok = true ; 				for  (int  _ = 1 ; _ <= s; _++) { 					pos++; 					num %= s; 					num++; 					if  (adj[pos][num]) { 						ok = false ; 					} 				} 				if  (ok) { 					f[i] += f[j]; 				} 			} 		} 	} 	cout << f[n] << endl; }; 
测样例发现算多了。
比如 1 2 3 4 1 2,从j = 2 j=2 j = 2 i = 6 i=6 i = 6 j = 4 j=4 j = 4 i = 6 i=6 i = 6 
计算重复只有可能是,两个段的r = 1 r=1 r = 1 s s s s s s 
修改 DP 数组为f i , s f_{i,s} f i , s  i i i s s s g i , s g_{i,s} g i , s  i i i s s s r = 1 r=1 r = 1 
转移的时候如果r = 1 r=1 r = 1 g g g 
总复杂度O ( n 4 ) \mathcal{O}(n^{4}) O ( n 4 ) 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 auto  solve = [&] {	int  n, m; 	cin >> n >> m; 	vector adj (n + 1 , vector<int >(n + 1 ))  ; 	while  (m--) { 		int  i, x; 		cin >> i >> x; 		adj[i][x] = 1 ; 	} 	vector f (n + 1 , vector<Z>(n + 1 ))  ; 	vector g (n + 1 , vector<Z>(n + 1 ))  ; 	f[0 ][0 ] = 1 ; 	for  (int  i = 1 ; i <= n; i++) { 		for  (int  j = 0 ; j < i; j++) { 			Z sum = 0 ; 			int  s = i - j; 			for  (int  r = 1 ; r <= s; r++) { 				int  pos = j; 				int  num = r - 1 ; 				bool  ok = true ; 				for  (int  _ = 1 ; _ <= s; _++) { 					pos++; 					num %= s; 					num++; 					if  (adj[pos][num]) { 						ok = false ; 					} 				} 				if  (ok) { 					for  (int  k = 0 ; k <= n; k++) { 						f[i][s] += f[j][k]; 						if  (r == 1 ) { 							g[i][s] += f[j][k]; 						} 					} 					if  (r == 1 ) { 						for  (int  k = s + 1 ; k <= n; k++) { 							f[i][s] -= g[j][k]; 						} 					} 				} 			} 		} 	} 	Z res = 0 ; 	for  (int  i = 1 ; i <= n; i++) { 		res += f[n][i]; 	} 	cout << res << endl; };