The 2024 ICPC Asia East Continent Online Contest (II) - Dashboard - Contest - QOJ.ac Dashboard - The 2024 ICPC Asia EC Regionals Online Contest (II) - Codeforces 
官方题解:2024 ICPC 网络赛 第二场简要题解 
不会 DP 不会字符串
机器人的活动范围距离起点的距离最大是d d d 
对于某个点,玩家到达步数是x x x y y y x x x y y y x ⩾ y x \geqslant y x ⩾ y x , y x,y x , y x x x y y y y y y y y y 
用 BFS 寻路。寻路的时候记录步数x x x y y y 
每个点都可以经过两次,所以 vis 等数组都开成二维的,奇偶相互独立。
注意输出路径时不能写 if (u == 1) break,可能玩家走 1->2->3->1 改变奇偶性,导致实际路径长度与输出的不符。在 BFS 里走到n n n 
Bonus:如果数据有d = 0 d=0 d = 0 
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 void  eachT ()      int  n, m, D;     cin >> n >> m >> D;     vector<vector<int >> E (n);     while  (m--) {         int  u, v;         cin >> u >> v;         u--, v--;         E[u].push_back (v);         E[v].push_back (u);     }     queue<pair<int , int >> Q;     vector val (n, array{ inf, inf })  ;     int  k;     cin >> k;     while  (k--) {         int  x;         cin >> x;         x--;         val[x][0 ] = 0 ;         Q.push ({ 0 , x });     }     while  (!Q.empty ()) {         auto  [d, u] = Q.front ();         Q.pop ();         if  (d >= D) continue ;         ++d;         for  (auto & v : E[u]) {             if  (val[v][d & 1 ] != inf) continue ;             val[v][d & 1 ] = d;             Q.push ({ d, v });         }     }     vector from (n, array{ -1 , -1  })  ;     Q.push ({ 0 , 0  });     while  (!Q.empty ()) {         auto  [d, u] = Q.front ();         Q.pop ();         if  (u == n - 1 ) {             cout << d << '\n' ;             vector<int > path;             while  (d >= 0 ) {                 path.push_back (u);                 u = from[u][d & 1 ];                 d--;             }             for  (int  i = path.size () - 1 ; i >= 0 ; --i) {                 cout << path[i] + 1  << ' ' ;             }             cout << '\n' ;             return ;         }         ++d;         for  (auto & v : E[u]) {             if  (d >= val[v][d & 1 ]) continue ;             if  (~from[v][d & 1 ]) continue ;             from[v][d & 1 ] = u;             Q.push ({ d, v });         }     }     cout << "-1\n" ; } 
每个数的期望次数是固定的,而且贪心地,大数再掷一次,小数等待。
分界线不知道,可以设分界线为x x x x x x 再 等待E E E 
E = 1 n ( 1 + 2 + ⋯ + x ) + n − x n ( E + 1 ) E=\frac{1}{n}(1+2+\dots+x)+\dfrac{n-x}{n}(E+1) E = n 1  ( 1 + 2 + ⋯ + x ) + n n − x  ( E + 1 ) 
化简得
E = x 2 + n x − 1 2 E=\frac{x}{2}+\frac{n}{x}-\frac{1}{2} E = 2 x  + x n  − 2 1  
是个对勾函数,欲求最小值,取x = 2 n x=\sqrt{2n} x = 2 n  
注意答案需要开 LL。
时间复杂度Θ ( T ) \Theta(T) Θ ( T ) 
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 #include  <iostream>  #include  <vector>  #include  <numeric>  #include  <cmath>  using  namespace  std;using  ll = long  long ;void  solve ()      int  n;     cin >> n;     ll x = sqrt (2  * n);     if  (x / 2.0  + 1.0  * n / x > (x + 1 ) / 2.0  + 1.0  * n / (x + 1 )) {         ++x;     }     ll f1 = x * x + 2  * n - x;     ll f2 = 2  * x;     ll d = gcd (f1, f2);     f1 /= d, f2 /= d;     cout << f1 << ' '  << f2 << '\n' ; } int  main ()      ios::sync_with_stdio (false );     cin.tie (nullptr );     cout.tie (nullptr );     int  T = 1 ;     cin >> T;     while  (T--) {         solve ();     }     return  0 ; } 
平局相当于再来一次,所以每小局概率就是二人获胜概率的比例。
筹码是按照辗转相减的方式减少的,用辗转相除加速辗转相减:
如果甲的筹码比乙少,必须一直赢,直到翻盘; 如果甲的筹码比乙多,每局都可以输或者赢,直至筹码比乙少; 最终两人筹码相同,赢的概率就是小局赢的概率。 具体式子不写了,见代码。
时间复杂度Θ ( T log  2 ) \Theta(T\log^{2}) Θ ( T log  2 ) 
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 77 78 79 #include  <iostream>  using  namespace  std;using  ll = long  long ;constexpr  int  mod = 998244353 ;ll qpow (ll a, ll n)   {    ll res = 1 ;     while  (n) {         if  (n & 1 ) res = res * a % mod;         a = a * a % mod;         n >>= 1 ;     }     return  res; } ll inv (ll n)   {    return  qpow (n, mod - 2 ); } void  solve ()      ll x, y, p0, p1, b;     cin >> x >> y >> p0 >> p1 >> b;     ll ssss = inv (p0 + p1);     p0 = p0 * ssss % mod;     p1 = p1 * ssss % mod;     ll invq = inv (p1 - 1 );     ll res = 0 , pow = 1 ;     while  (x && y) {         if  (x == y) {             res += pow * p0 % mod;             res %= mod;             break ;         }         else  if  (x > y) {             int  q = x / y, r = x % y;             res += pow * p0 % mod * (qpow (p1, q) - 1 ) % mod * invq % mod;             res %= mod;             res += mod;             res %= mod;             pow *= qpow (p1, q);             pow %= mod;             x = r;         }         else  {               int  q = y / x, r = y % x;             if  (r == 0 ) {                 q--;                 r = x;             }             pow *= qpow (p0, q);             pow %= mod;             y = r;         }     }     cout << res << '\n' ; } int  main ()      ios::sync_with_stdio (false );     cin.tie (nullptr );     cout.tie (nullptr );     int  T;     cin >> T;     while  (T--) {         solve ();     }     return  0 ; } 
首先c i c_{i} c i  w n + 1 − i w_{n+1-i} w n + 1 − i  c 1 , w n c_{1},w_{n} c 1  , w n  w 1 , c n w_{1},c_{n} w 1  , c n  ∑ c w \sum cw ∑ c w c w \cfrac{c}{w} w c  
用调整法证明:欲求式
S = ∑ i = 1 n ( c i ∑ j = i + 1 n w j ) S=\sum_{i=1}^{n}\left(c_{i}\sum_{j=i+1}^{n}w_{j} \right) S = i = 1 ∑ n  ( c i  j = i + 1 ∑ n  w j  ) 
若记交换k , k + 1 k,k+1 k , k + 1 S ′ S' S ′ 
S ′ − S = c k + 1 w k − c k w k + 1 S'-S=c_{k+1}w_{k}-c_{k}w_{k+1} S ′ − S = c k + 1  w k  − c k  w k + 1  
如果有c k w k < c k + 1 w k + 1 \cfrac{c_{k}}{w_{k}}<\cfrac{c_{k+1}}{w_{k+1}} w k  c k   < w k + 1  c k + 1   S ′ − S > 0 S'-S>0 S ′ − S > 0 c k w k < c k + 1 w k + 1 \cfrac{c_{k}}{w_{k}}<\cfrac{c_{k+1}}{w_{k+1}} w k  c k   < w k + 1  c k + 1   k , k + 1 k,k+1 k , k + 1 c w \cfrac{c}{w} w c  
读入需要 LL。
时间复杂度Θ ( n log  n ) \Theta(n\log n) Θ ( n log  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 25 26 27 28 29 30 31 32 33 34 35 36 37 38 #include  <iostream>  #include  <vector>  #include  <algorithm>  using  namespace  std;using  ll = long  long ;int  main ()      ios::sync_with_stdio (false );     cin.tie (nullptr );     cout.tie (nullptr );     int  n;     cin >> n;     vector<pair<ll, ll>> a (n);     ll res = 0 ;     for  (int  i = 0 ; i < n; ++i) {         ll w, v, c;         cin >> w >> v >> c;         res += v;         a[i] = { w, c };     }     sort (a.begin (), a.end (),         [&](const  pair<ll, ll>& a, const  pair<ll, ll>& b) {         return  1ll  * a.first * b.second < 1ll  * b.first * a.second;     });     ll sumc = 0 ;     for  (int  i = 0 ; i < n; ++i) {         res -= a[i].first * sumc;         sumc += a[i].second;     }     cout << res << '\n' ;     return  0 ; } 
低位有1 1 1 0 0 0 0 0 0 1 -> 1 -1 -1 -1。而末尾的0 0 0 0 0 0 
时间复杂度Θ ( T log  n ) \Theta(T\log n) Θ ( T log  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 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 #include  <iostream>  #include  <vector>  using  namespace  std;using  ll = long  long ;void  solve ()      int  n;     cin >> n;     if  (n == 0  || (n & -n) > 2 ) {         cout << "NO\n" ;         return ;     }     int  D = 32 ;     vector<int > a (D)  ;     for  (int  bit = 0 ; bit < D; ++bit) {         a[bit] = n >> bit & 1 ;         if  (bit && !a[bit] && a[bit - 1 ]) {             a[bit] = 1 ;             a[bit - 1 ] = -1 ;         }     }     cout << "YES\n" ;     for  (int  bit = 0 ; bit < D; ++bit) {         cout << a[bit] << " \n" [(bit + 1 ) % 8  == 0 ];     } } int  main ()      ios::sync_with_stdio (false );     cin.tie (nullptr );     cout.tie (nullptr );     int  T = 1 ;     cin >> T;     while  (T--) {         solve ();     }     return  0 ; } 
选择容量最小的赛站,最坏高手都在自己这个赛站。按排名从高到低依次统计答案,用桶记次数。
时间复杂度Θ ( n log  n ) \Theta(n\log n) Θ ( n log  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 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 #include  <iostream>  #include  <algorithm>  #include  <vector>  #include  <unordered_map>  using  namespace  std;using  ll = long  long ;const  int  inf = 0x3f3f3f3f ;struct  node  {    int  x;     string s;     int  id;     int  ans; }; int  main ()      ios::sync_with_stdio (false );     cin.tie (nullptr );     cout.tie (nullptr );     int  n, k;     cin >> n >> k;     int  minn = inf;     for  (int  i = 0 ; i < k; i++) {         int  x;         cin >> x;         minn = min (minn, x);     }     vector<node> a (n)  ;     for  (int  i = 0 ; i < n; i++) {         int  x;         string s;         cin >> x >> s;         a[i] = { x, s, i, 0  };     }     sort (a.begin (), a.end (), [&](const  auto & A, const  auto & B) {         return  A.x > B.x;     });     unordered_map<string, int > cnt;     int  sum = 0 ;       for  (int  i = 0 ; i < n; i++) {         a[i].ans = sum - (cnt[a[i].s] == minn);         if  (cnt[a[i].s] < minn) {             cnt[a[i].s]++;             sum++;         }     }     sort (a.begin (), a.end (), [&](const  auto & A, const  auto & B) {         return  A.id < B.id;     });     for  (int  i = 0 ; i < n; i++) {         cout << a[i].ans + 1  << endl;     }     return  0 ; } 
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 #include  <iostream>  using  namespace  std;using  ll = long  long ;int  main ()      ios::sync_with_stdio (false );     cin.tie (nullptr );     cout.tie (nullptr );     int  n;     cin >> n;     ll sum = 1500 ;     for  (int  i = 0 ; i < n; ++i) {         int  x;         cin >> x;         sum += x;         if  (sum >= 4000 ) {             cout << i + 1  << '\n' ;             return  0 ;         }     }     cout << -1  << '\n' ;     return  0 ; }