構造  800Q . \Large\mathcal{Q}. Q .   給定n n n   和k k k  ,找出長度最小的字符串s s s  ,使得所有長度爲n n n   的用前k k k   个小寫英文字母組成的字符串都是s s s   的子串。(CF1925A. We Got Everything Covered! )
A . \Large\mathcal{A}. A . s = a b c … x a b c … x … a b c … x s=abc\dots xabc\dots x\dots abc\dots x s = a b c … x a b c … x … a b c … x 
Q . \Large\mathcal{Q}. Q .   規定一个數列的求和方法,從前向後遍歷,若這一項大於前一項,按常規方式求和,否則將和清零。在 1 到 n 的全排列中找出和的最大值。(VJwin4D, CF1728B. Best Permutation )
A . \Large\mathcal{A}. A . { If  n = 2 k : 2 k − 2 ,   2 k − 3 ,   … ,   3 ,   2 ,   1 ,   2 k − 1 ,   2 k If  n = 2 k + 1 : 1 ,   2 k − 1 ,   2 k − 2 ,   2 k − 3 ,   … ,   3 ,   2 ,   2 k ,   2 k + 1 \begin{cases}\text{If}n=2k: & 2k-2,~ 2k-3,~ \dots,~ 3,~ 2,~ 1,~ 2k-1,~ 2k \\ \text{If}n=2k+1: & 1,~ 2k-1,~ 2k-2,~ 2k-3,~ \dots,~ 3,~ 2,~ 2k,~ 2k+1\end{cases} { If  n = 2 k : If  n = 2 k + 1 :  2 k − 2 ,   2 k − 3 ,   … ,   3 ,   2 ,   1 ,   2 k − 1 ,   2 k 1 ,   2 k − 1 ,   2 k − 2 ,   2 k − 3 ,   … ,   3 ,   2 ,   2 k ,   2 k + 1  
  900Q . \Large\mathcal{Q}. Q .   給定正整數數列{ a n } \lbrace a_n \rbrace { a n  }  ,構造{ b n } \lbrace b_n \rbrace { b n  }  ,滿足a i ≠ b i ( 1 ⩽ i ⩽ n ) a_i \ne b_i(1\leqslant i\leqslant n) a i   = b i  ( 1 ⩽ i ⩽ n )  ,∑ i = 1 n a i = ∑ i = 1 n b i \sum\limits_{i=1}^{n} a_i = \sum\limits_{i=1}^{n} b_i i = 1 ∑ n  a i  = i = 1 ∑ n  b i   。(VJwin14J, CF1856B. Good Arrays )
A . \Large\mathcal{A}. A .   如果某个元素是 1,那至少給它增加 1,我們只需要看非 1 的元素減少的量夠不夠給它增加 1,也就是它們的總和是否大於 n,再特判 n=1 的情形即可。
1 2 3 4 5 6 ll n = read (), sum = 0 ; for  (int  i = 0 ; i < n; ++i) {    int  x = read ();     if  (x > 1 ) sum += x; } printf ("%s\n" , n > 1  && sum >= n ? "Yes"  : "No" );
另一種(或許更容易理解的)思路是:分別計算當前總和以及所需的最小和 wt。
1 2 3 4 5 6 7 8 ll n = read (), sum = 0 , wt = 0 ; for  (int  i = 0 ; i < n; ++i) {    int  x = read ();     sum += x;     if  (x > 1 ) wt += 1 ;     else  wt += 2 ; } printf ("%s\n" , n > 1  && sum >= wt ? "Yes"  : "No" );
事實上上述兩種方法等價。
  1800Q . \Large\mathcal{Q}. Q .   構造一個序列,任何集合{ x ∣ 1 ⩽ x ⩽ n ∧ x ≠ k } \lbrace x \mid 1\leqslant x\leqslant n \land x\ne k \rbrace { x ∣ 1 ⩽ x ⩽ n ∧ x  = k }   中的數i i i   都可以是某個子序列的元素之和。(CF1966D. Missing Subsequence Sum )
A . \Large\mathcal{A}. A . 
引理  如果我們已經能表示1 ∼ s 1\sim s 1 ∼ s  ,且擁有數t > s t>s t > s  ,則能表示t ∼ t + s t\sim t+s t ∼ t + s  。
問題 1  求一個數組,任何滿足1 ∼ n 1 \sim n 1 ∼ n   的數i i i   都可以是某個子序列的元素之和。
問題 1 的解答 取{ 1 ,   2 ,   4 ,   … ,   2 w } \lbrace 1,~2,~4,~\dots,~2^{w} \rbrace { 1 ,   2 ,   4 ,   … ,   2 w }  ,其中2 w ⩾ n 2^w\geqslant n 2 w ⩾ n  ,具体地應取⌈ log  2 ( n ) ⌉ − 1 \lceil\log_2(n)\rceil-1 ⌈ log  2  ( n ) ⌉ − 1  。爲敘述方便,以下記w = ⌈ log  2 ( n ) ⌉ − 1 w=\lceil\log_2(n)\rceil - 1 w = ⌈ log  2  ( n ) ⌉ − 1  。 問題 2  求一個數組,所有子序列的和恰好是1 ∼ n 1 \sim n 1 ∼ n  。
問題 2 的解答 注意到取{ 1 ,   2 ,   4 ,   … ,   2 w − 1 } \lbrace 1,~2,~4,~\dots,~2^{w-1} \rbrace { 1 ,   2 ,   4 ,   … ,   2 w − 1 }   可表示1 ∼ 2 w − 1 1 \sim 2^{w}-1 1 ∼ 2 w − 1  ,爲了恰好表示到n n n  ,希望表示? ∼ n ? \sim n ? ∼ n  ,根據引理,只需擁有數n − ( 2 w − 1 ) n-(2^{w}-1) n − ( 2 w − 1 )   即可,因此我們取{ 1 ,   2 ,   4 ,   … ,   2 w − 1 ,   n − ( 2 w − 1 ) } \lbrace 1,~2,~4,~\dots,~2^{w-1},~n-(2^{w}-1) \rbrace { 1 ,   2 ,   4 ,   … ,   2 w − 1 ,   n − ( 2 w − 1 ) }  。 問題 3  現在已經恰好能表示1 ∼ k − 1 1\sim k-1 1 ∼ k − 1  ,求一個數組,任何滿足k + 1 ∼ n k+1 \sim n k + 1 ∼ n   的數i i i   都可以是某個子序列的元素之和。
問題 3 的解答 根據引理,已經擁有k + 1 k+1 k + 1  ,因此可表示k + 1 ∼ ( k + 1 + k − 1 = 2 k ) k+1\sim (k+1+k-1=2k) k + 1 ∼ ( k + 1 + k − 1 = 2 k )  ,若是再擁有2 k + 1 2k+1 2 k + 1  ,因此可表示2 k + 1 ∼ 3 k 2k+1\sim 3k 2 k + 1 ∼ 3 k  ,再擁有3 k + 1 3k+1 3 k + 1  ,因此可表示3 k + 1 ∼ 4 k 3k+1\sim 4k 3 k + 1 ∼ 4 k  。當然,此過程不能無限進行,畢竟有步數限制。但幸運的是,當擁有k + 1 , 2 k + 1 , 3 k + 1 k+1,2k+1,3k+1 k + 1 , 2 k + 1 , 3 k + 1   時,我們已經可以表示k + 1 ∼ 6 k + 1 k+1\sim 6k+1 k + 1 ∼ 6 k + 1   了,此時再添加6 k + 2 6k+2 6 k + 2  ,便可表示k + 1 ∼ 12 k + 3 k+1\sim 12k+3 k + 1 ∼ 1 2 k + 3  ,如此倍增,就能表示題設要求的所有數。 原問題的解答  根據問題 2,先取{ 1 ,   2 ,   4 ,   … ,   2 v − 1 ,   k − ( 2 v − 1 ) } \lbrace 1,~2,~4,~\dots,~2^{v-1},~k-(2^{v}-1) \rbrace { 1 ,   2 ,   4 ,   … ,   2 v − 1 ,   k − ( 2 v − 1 ) }  ,根據問題 3,再取{ k + 1 ,   2 k + 1 ,   3 k + 1 ,   2 ( 3 k + 1 ) ,   2 2 ( 3 k + 1 ) ,   …   } \lbrace k+1,~2k+1,~3k+1,~2(3k+1),~2^2(3k+1),~\dots\rbrace { k + 1 ,   2 k + 1 ,   3 k + 1 ,   2 ( 3 k + 1 ) ,   2 2 ( 3 k + 1 ) ,   … }  ,即是問題的答案。
1 2 3 4 5 6 7 8 9 10 int  n = read (), k = read ();int  bit = 0 ; while  ((1ll  << bit) <= k) ++bit; --bit;vector<int > ans; for  (int  i = 0 ; i < bit; ++i) ans.push_back (1ll  << i);if  (k - (1ll  << bit)) ans.push_back (k - (1ll  << bit));if  (k + 1  <= n) ans.push_back (k + 1 );if  (2  * k + 1  <= n) ans.push_back (2  * k + 1 );if  (3  * k + 1  <= n) ans.push_back (3  * k + 1 );for  (int  x = 6  * k + 2 ; x <= n; x <<= 1 ) ans.push_back (x);print (ans);
Q . \Large\mathcal{Q}. Q .   給定n n n  ,輸出一个數列,其中包含n n n   个遞增子列。(CF1922E. Increasing Subsequences )
A . \Large\mathcal{A}. A .   注意到{ 0 , 1 , … , x − 1 } \{0,1,\dots,x-1\} { 0 , 1 , … , x − 1 }   中有2 x 2^x 2 x   个遞增子列,我們對n n n   作二進制拆分,即n = 2 a 0 + 2 a 1 + ⋯ + 2 a k n=2^{a_0}+2^{a_1}+\dots+2^{a_k} n = 2 a 0  + 2 a 1  + ⋯ + 2 a k   ,首先輸出0 ∼ a k − 1 0\sim a_k-1 0 ∼ a k  − 1  ,對於其它二進制位,可以錯位構造a i a^i a i   个數,但爲了節約輸出的个數,我們藉助第一位輸出的數,直接輸出a i a_i a i    即可。最終的輸出結果是0 , 1 , … , a k − 1 , a k − 1 , a k − 2 , … , a 0 0,1,\dots,a_k-1,a_{k-1},a_{k-2},\dots,a_0 0 , 1 , … , a k  − 1 , a k − 1  , a k − 2  , … , a 0   。
1 2 3 4 5 6 7 8 ll n = read (); vector<int > ans; ll tmp = n, bit = -1 ; while  (tmp) ++bit, tmp >>= 1 ;  for  (int  i = 0 ; i < bit; ++i) ans.emplace_back (i); while  (bit--) if  (n & (1ll  << bit)) ans.emplace_back (bit); printf ("%lld\n" , ans.size ());for  (auto  i : ans) printf ("%d " , ans[i]);printf ("\n" );
  1900Q . \Large\mathcal{Q}. Q .   给定n , k n,k n , k  ,构造n n n   个四元组,满足所有四元组的所有元素互不相同,且每个四元组的最大公约数皆为k k k  。求所有元素最大值最小的一组构造。
A . \Large\mathcal{A}. A .   首先把所有四元组除以k k k   ,那么所有四元组的最大公约数为1 1 1  。注意到,任意一个四元组都只能存在一个偶数,至少三个奇数,于是元素最大值的下界为6 ( n − 1 ) + 5 = 6 n − 1 6(n-1)+5=6n-1 6 ( n − 1 ) + 5 = 6 n − 1  。另一方面,每个四元组取6 i + 1 , 6 i + 2 , 6 i + 3 , 6 i + 5 ( 0 ⩽ i < n ) 6i+1,6i+2,6i+3,6i+5(0\leqslant i<n) 6 i + 1 , 6 i + 2 , 6 i + 3 , 6 i + 5 ( 0 ⩽ i < n )  。
  2300Q . \Large\mathcal{Q}. Q .   每次操作可選擇一个二元组( x i , y i ) (x_i,y_i) ( x i  , y i  )  ,使得a x i a_{x_i} a x i     和a y i a_{y_i} a y i     的值變爲f ( a x i , a y i ) f(a_{x_i},a_{y_i}) f ( a x i   , a y i   )  。f ( x , y ) f(x,y) f ( x , y )   的值未知,但對於相同的x , y x,y x , y  ,f ( x , y ) f(x,y) f ( x , y )   的值相同。給出一種操作方案使任意函數f f f   經過若干次操作後數列中最多只有2 2 2   个不同的數。(VJwin7F, CF1408F. Two Different )
A . \Large\mathcal{A}. A .   顯然,若數列的長度是n = 2 k n=2^k n = 2 k  ,可分成2 k − 1 2^{k-1} 2 k − 1   組,兩兩操作,再錯位着操作,最終會全部相同。比如對於n = 8 n=8 n = 8  ,可以這樣操作:| 1 2 3 4 5 6 7 8 || 1 3 2 4 5 7 6 8 || 1 5 2 6 3 7 4 8 |。那麼如果不是2 2 2   的冪呢?比如n = 9 n=9 n = 9  ,劃分爲9 = 8 + 1 = 4 + 5 9=8+1=4+5 9 = 8 + 1 = 4 + 5  ?實操後發現不行,實際上,不一定做加法拆分,可以先對前8 8 8   个操作,然後借用第2   8 2~8 2   8   个元素和後面第9 9 9   个元素一併操作,也就是 | 1 2 3 4 5 6 7 8 || 1 3 2 4 5 7 6 8 || 1 5 2 6 3 7 4 8 |||| 2 3 4 5 6 7 8 9 || 2 4 3 5 6 8 7 9 || 2 6 3 7 4 8 5 9 |。現在只要把這些數字輸出來就好了。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 int  cnt = -1 , t = n;while  (t) { cnt++; t >>= 1 ; }t = 1  << cnt;   for  (int  i = cnt; i >= 1 ; --i) {     for  (int  j = 1 ; j <= (1  << i) / 2 ; j++) {          for  (int  k = 1 ; k <= t / (1  << i); k++) {              printf ("%d %d\n" , k + t * 2  / (1  << i) * (j - 1 ), k + t * 2  / (1  << i) * (j - 1 ) + t / (1  << i));          }     } } for  (int  i = cnt; i >= 1 ; --i) {    for  (int  j = 1 ; j <= (1  << i) / 2 ; j++) {         for  (int  k = 1 ; k <= t / (1  << i); k++) {             printf ("%d %d\n" , n - t + k + t * 2  / (1  << i) * (j - 1 ), n - t + k + t * 2  / (1  << i) * (j - 1 ) + t / (1  << i));         }     } } 
輸出練習題
BUC1E 杨辉三角