像是游戏书的思维题 
大方向是,用最少步骤得到一个确定的数y y y n − y n-y n − y 
C1:由于初始x x x x ⩽ 16 x \leqslant 16 x ⩽ 1 6 x = 1 x=1 x = 1 6 + 1 = 7 6 + 1 = 7 6 + 1 = 7 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 int  n;cin >> n; int  x;cout << "digit"  << endl; cin >> x; cout << "digit"  << endl; cin >> x; cout << "add "  << -8  << endl; cin >> x; cout << "add "  << -4  << endl; cin >> x; cout << "add "  << -2  << endl; cin >> x; cout << "add "  << -1  << endl; cin >> x; cout << "add "  << n - 1  << endl; cin >> x; cout << "!"  << endl; cin >> x;  
C2:不好解释。。敲了半小时计算器发现的
1 2 3 4 5 6 7 8 9 10 11 12 13 int  n;cin >> n; int  x;cout << "mul "  << 9  << endl; cin >> x; cout << "digit"  << endl; cin >> x; cout << "digit"  << endl; cin >> x; cout << "add "  << n - 9  << endl; cin >> x; cout << "!"  << endl; cin >> x; 
C3:呃,比较熟知的结果是 7 * 9 = 63,7 * 99,999 = 699,993,想到这一点应该就能试出来
1 2 3 4 5 6 7 8 9 10 11 12 13 int  n;cin >> n; int  x;cout << "mul "  << 999999999  << endl; cin >> x; cout << "digit"  << endl; cin >> x; if  (n - 81 ) {	cout << "add "  << n - 81  << endl; 	cin >> x; } cout << "!"  << endl; cin >> x; 
脑电波题蛙,作为算法竞赛题真合适吗 
给个证明:设N = 999999999 = 1 0 9 − 1 N = 999999999 = 10^9 - 1 N = 9 9 9 9 9 9 9 9 9 = 1 0 9 − 1 n ⩽ 1 0 9 n \leqslant 10^9 n ⩽ 1 0 9 S ( N n ) = 81 S(Nn) = 81 S ( N n ) = 8 1 S ( x ) S(x) S ( x ) x x x 
证明:9 是最大的数位,因此S ( N − x ) = S ( N ) − S ( x ) = 81 − S ( x ) S(N-x)=S(N)-S(x)=81-S(x) S ( N − x ) = S ( N ) − S ( x ) = 8 1 − S ( x ) 0 ⩽ x ⩽ N 0 \leqslant x \leqslant N 0 ⩽ x ⩽ N 
81 = S ( x ) + S ( N − x ) = S ( x ⋅ 1 0 9 ) + S ( N − x ) \begin{aligned} 81 &= S(x) + S(N-x) \\ &= S(x \cdot 10^{9}) + S(N-x) \end{aligned} 8 1  = S ( x ) + S ( N − x ) = S ( x ⋅ 1 0 9 ) + S ( N − x )  
由于x ⋅ 1 0 9 x \cdot 10^{9} x ⋅ 1 0 9 N − x N-x N − x 
81 = S ( x ⋅ 1 0 9 ) + S ( N − x ) = S ( x ⋅ 1 0 9 + N − x ) = S [ x ⋅ ( 1 0 9 − 1 ) + N ] = S ( N x + N ) = S [ ( x + 1 ) N ] \begin{aligned} 81 &= S(x \cdot 10^{9}) + S(N-x) \\ &= S(x \cdot 10^{9} + N-x) \\ &= S[x \cdot (10^{9}-1) + N] \\ &= S(Nx+N) \\ &= S[(x+1)N] \end{aligned} 8 1  = S ( x ⋅ 1 0 9 ) + S ( N − x ) = S ( x ⋅ 1 0 9 + N − x ) = S [ x ⋅ ( 1 0 9 − 1 ) + N ] = S ( N x + N ) = S [ ( x + 1 ) N ]  
再令y = x + 1 ∈ [ 1 , 1 0 9 ] y=x+1\in[1,10^{9}] y = x + 1 ∈ [ 1 , 1 0 9 ] S ( N y ) = 81 S(Ny)=81 S ( N y ) = 8 1 
对每个顶点,BFS 计算奇数步和偶数步最短路。
考虑将所有可用的步长数字加起来,并判断奇偶性。如果 sum 是偶数就与偶数步最短路比较,否则 sum 是奇数就与奇数步最短路比较,sum 大于等于 dis 就可达。
或者,需要改变 sum 的奇偶性。最优策略是从 sum 中减去最小的奇数步长 minodd,得到新的总和 sum2,sum2 大于等于 dis 就可达。
复杂度O  ( n + m + l ) \operatorname{O}(n+m+l) O ( n + m + l ) 
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 74 75 76 #include  <bits/stdc++.h>  using  namespace  std;using  ll = long  long ;constexpr  ll inf = 0x3f3f3f3f3f3f3f3f ;int  main ()      ios::sync_with_stdio (false );     cin.tie (nullptr ), cout.tie (nullptr );     int  t;     cin >> t;     while  (t--) {         int  n, m, l;         cin >> n >> m >> l;         ll minodd = inf;           ll sum = 0 ;         while  (l--) {             int  x;             cin >> x;             if  (x & 1 ) {                 minodd = min <ll>(minodd, x);             }             sum += x;         }         ll sum2 = sum - minodd;                    vector<vector<int >> E (2  * n);         auto  add = [&](int  u, int  v) {             E[u].push_back (v);             E[v].push_back (u);         };         while  (m--) {             int  u, v;             cin >> u >> v;             u--;             v--;             add (u, v + n);             add (u + n, v);         }                  vector<int > dis (2  * n, -1 )  ;         dis[0 ] = 0 ;         queue<int > Q;         Q.push (0 );         while  (!Q.empty ()) {             int  u = Q.front ();             Q.pop ();             for  (auto & v : E[u]) {                 if  (dis[v] != -1 ) continue ;                 dis[v] = dis[u] + 1 ;                 Q.push (v);             }         }         string res (n, '0' )  ;         for  (int  i = 0 ; i < 2  * n; i++) {             if  (dis[i] == -1 ) continue ;             if  (dis[i] % 2  == sum % 2 ) {                 if  (dis[i] <= sum) {                     res[i % n] = '1' ;                 }             } else  {                 if  (dis[i] <= sum2) {                     res[i % n] = '1' ;                 }             }         }         cout << res << endl;                     }     return  0 ; } 
第i i i d p i , j dp_{i,j} d p i , j  i i i j j j 
考虑转移d p i , j ← d p i − 1 , k dp_{i,j}\leftarrow dp_{i-1,k} d p i , j  ← d p i − 1 , k  i i i j − k j-k j − k i i i s i = 0 s_{i}=0 s i  = 0 i i i j j j i i i ( ⌈ j 2 ⌉ j − k ) \dbinom{\lceil \frac{j}{2} \rceil}{j-k} ( j − k ⌈ 2 j  ⌉  ) s i = 1 s_{i}=1 s i  = 1 ( ⌊ j 2 ⌋ j − k ) \dbinom{\lfloor \frac{j}{2} \rfloor}{j-k} ( j − k ⌊ 2 j  ⌋  ) 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 int  N, K;string S; cin >> N >> K >> S; vector<Z> f (K + 1 )  ;f[0 ] = 1 ; for  (int  i = N - 1 ; i >= 0 ; i--) {	vector<Z> nf (K + 1 )  ; 	for  (int  j = 0 ; j <= K; j++) { 		for  (int  k = 0 ; k <= j; k++) { 			nf[j] += f[k] * binom ((j + (S[i] == '0' )) / 2 , j - k); 		} 	} 	f = nf; } cout << f[K] << endl;