∑ i = 1 n ( a i − a i + k ) = ∑ i = 1 k a i − ∑ i = n + 1 n + k a i \sum_{i=1}^{n}(a_{i}-a_{i+k})=\sum_{i=1}^{k}a_{i}-\sum_{i=n+1}^{n+k}a_{i} i = 1 ∑ n  ( a i  − a i + k  ) = i = 1 ∑ k  a i  − i = n + 1 ∑ n + k  a i  
约瑟夫环问题 
设J n , m J_{n, m} J n , m  n , m n, m n , m 
J n , m = ( J n − 1 , m + m )   m o d   n J_{n, m}=\left(J_{n-1, m}+m\right) \bmod n J n , m  = ( J n − 1 , m  + m ) m o d n 
这个也很好推。从 0 开始数m m m m − 1 m-1 m − 1 n − 1 n-1 n − 1 n − 1 n-1 n − 1 m m m 
题目说是从k k k k k k 
时间复杂度Θ ( n ) \Theta(n) Θ ( n ) 
1 2 3 4 5 int  res = 0 ;for  (int  i = 2 ; i <= n; ++i) {    res = (res + m) % i; } cout << ((res + k - 1 ) % n + 1 ) << '\n' ; 
时间复杂度Θ ( k log  n ) \Theta(k\log n) Θ ( k log  n ) 
1 2 3 4 5 6 7 8 9 10 int  josephus (int  n, int  k)      if  (n == 1 ) return  0 ;     if  (k == 1 ) return  n - 1 ;     if  (k > n) return  (josephus (n - 1 , k) + k) % n;       int  res = josephus (n - n / k, k);     res -= n % k;     if  (res < 0 ) res += n;       else  res += res / (k - 1 );       return  res; } 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 void  eachT ()      ll p = read (), a = read (), b = read ();     ll q = read (), c = read (), d = read ();     ll m = read (), t = read ();     ll res = 0 ;     int  cnt = 0 ;     while  (t >= b + d) {                  ll x = m / p;         if  (x == 0 ) break ;         ll lun = min (((x + 1 ) * p - m + ((q - p) * x) - 1 ) / ((q - p) * x), t / ((a + c) * x + (b + d)));         if  (lun == 0 ) {             x = min (x, (t - (b + d)) / (a + c));             lun = 1 ;         }         if  (x == 0 ) break ;         m += lun * ((q - p) * x);         t -= lun * ((a + c) * x + (b + d));     }     printf ("%lld\n" , m);      } 
[[…/contests/2024 杭电多校 /2024-08-16:2024“钉耙编程”中国大学生算法设计超级联赛(9)|2024-08-16:2024“钉耙编程”中国大学生算法设计超级联赛(9)]]
赛时代码:
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 void  eachT ()      ll k = read (), x = read (), y = read ();     ll mx = max (x, y);     ll mn = min (x, y);     if  (x == y) {         if  (((k + x - 1 ) / x) & 1 ) {             printf ("Yes\nNo\n" );         }         else  {             printf ("No\nYes\n" );         }         return ;     }     ll m = k / mx;     if  (m * mx == k) {            m--;     }     if  ((m + 1 ) * mn >= k) {         if  (m & 1 ) {             printf ("No\nYes\n" );         }         else  {             printf ("Yes\nNo\n" );         }         return ;     }     printf ("Yes\nYes\n" ); } 
优化:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 void  eachT ()      ll k = read (), x = read (), y = read ();     if  (x > y) swap (x, y);     ll m = (k + y - 1 ) / y;     if  (m * x >= k) {         if  (m & 1 ) {             printf ("Yes\nNo\n" );         }         else  {             printf ("No\nYes\n" );         }     }     else  {         printf ("Yes\nYes\n" );     } } 
[[…/contests/2024 杭电多校 /2024-08-16:2024“钉耙编程”中国大学生算法设计超级联赛(9)|2024-08-16:2024“钉耙编程”中国大学生算法设计超级联赛(9)]]
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 signed  main ()      int  t;     cin >> t;     while  (t--) {         int  n;         cin >> n;         set<int >a;         int  tmp;         for  (int  i = 1 ; i <= n; i++) {             cin >> tmp;             a.insert (tmp);         }         for  (int  i = 1 ; i <= n; i++) {             cin >> tmp;         }         int  pr = n - a.size ();         int  only = a.size () - pr;         if  (pr) {               cout << "shuishui"  << endl;         }         else  {             cout << "sha7dow"  << endl;         }     }     return  0 ; } 
已知在k k k a xor  b = c a\operatorname{xor} b=c a x o r b = c xor  \operatorname{xor} x o r k k k 
思路 k ∣ a + b − c k\mid a+b-c k ∣ a + b − c 
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 ll a = read (), b = read (), c = read (); ll v = a + b - c; if  (v < 0 ) {    printf ("0\n" ); } else  if  (v == 0 ) {    printf ("-1\n" ); } else  {    auto  solve = [&](ll x) {         ll A = a, B = b, C = c;         while  (A || B || C) {             if  ((A % x + B % x) % x != C % x) {                 return  0 ;             }             A /= x, B /= x, C /= x;         }         return  1 ;     };     int  ans = 0 ;     for  (ll i = 2 ; i * i <= v; ++i) {         if  (v % i) continue ;         ans += solve (i);         if  (i * i != v) ans += solve (v / i);     }     if  (v > 1 ) ans += solve (v);     printf ("%d\n" , ans); } 
[[…/contests/2024 牛客多校 /2024-07-23:2024 牛客暑期多校训练营 3#A - Bridging the Gap 2|2024-07-23:2024 牛客暑期多校训练营 3]]
题意 n n n i i i h i h_{i} h i  L L L R R R 
解  最后一趟一定运R R R R R R L L L R − L R-L R − L t = ⌊ n − R R − L ⌋ t=\left\lfloor \frac{n-R}{R-L} \right\rfloor t = ⌊ R − L n − R  ⌋ R R R L L L f f f 
前t t t R + L R+L R + L n − R − t ( R − L ) + L n - R - t(R - L)+L n − R − t ( R − L ) + L L L L n − R − t ( R − L ) + 2 L n - R - t(R - L)+2L n − R − t ( R − L ) + 2 L R R R 
再看能消耗的体力值。设总轮数l = 2 ( t + f ) + 1 l=2(t+f)+1 l = 2 ( t + f ) + 1 h i ⩾ l h_{i} \geqslant l h i  ⩾ l h i ← l h_{i} \leftarrow l h i  ← l h i h_{i} h i  ∑ h i \sum h_{i} ∑ h i  
只需判断是否满足需要消耗的体力值⩾ \geqslant ⩾ 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 ll n = read (), L = read (), R = read (); int  flag = 0 ;ll sum = 0 ; ll t1 = (n - R) / (R - L); if  ((n - R) % (R - L)) {    flag = 1 ; } ll lun = 2  * (t1 + flag) + 1 ; for  (int  i = 1 ; i <= n; i++) {    int  x = read ();     if  (!(x & 1 )) x -= 1 ;     if  (x > lun) x = lun;     sum += x; } ll lhs = 0 ; if  (flag) lhs = (n - R - t1 * (R - L)) + 2  * L;lhs += t1 * (R + L) + R; cout << (lhs <= sum ? "Yes"  : "No" ) << "\n" ; 
题意  需要造出若干台战争机器对抗怪兽。每台机器有战斗和创造功能:
战斗:使怪兽血量减 1,然后失去所有功能; 创造:m m m k   ( k ⩽ m ) k\ (k \leqslant m) k   ( k ⩽ m ) m m m  怪兽的初始血量为h h h 0 0 0 
称能继续创造的机器是有用的,每次创造操作相当于减少了m − k m-k m − k m m m k k k k k k x x x m ( x + 1 ) + k ⩾ h m(x+1)+k \geqslant h m ( x + 1 ) + k ⩾ h m + x ( m − k ) m+x(m-k) m + x ( m − k ) x − 1 x-1 x − 1 m x + k + r = h mx+k+r=h m x + k + r = h m + ( x − 1 ) ( m − k ) + r m+(x-1)(m-k)+r m + ( x − 1 ) ( m − k ) + r 
1 2 3 4 5 6 7 int  m, k, h;cin >> m >> k >> h; int  x = (h - k) / m;int  del = h - k - x * m;int  ans1 = m + (x - 1 ) * (m - k) + del;int  ans2 = m + x * (m - k);cout << (h == 0  ? 0  : min (ans1, ans2)) << endl; 
[[…/contests/2024 牛客多校 /2024-08-15:2024 牛客暑期多校训练营 10|2024-08-15:2024 牛客暑期多校训练营 10]]
题意  两个玩家在一场公平的游戏里互相全押。当赢家筹码不少于输家时,游戏立即结束;否则输家向赢家支付等同于赢家筹码的筹码。问两个玩家的胜率。
思路  注意到a a + b \cfrac{a}{a+b} a + b a  i i i 1 1 1 i i i a > b a>b a > b a a + b , b a + b \cfrac{a}{a+b},\cfrac{b}{a+b} a + b a  , a + b b  
题意  有一个长度为n n n i i i s i s_i s i  < 或 >。当弹球放在其中一个格子上时,它会按照以下规则移动:
如果弹球位于第i i i s i s_i s i  <,则弹球在下一秒会向左移动一个单元格; 如果s i s_i s i  >,则向右移动一个单元格; 弹球移动后,字符s i s_i s i   对于每个i i i i i i 
思路  设起始向左走,且从左边出,答案为
( i − l 1 ) + ( r 1 − l 1 ) + ( r 1 − l 2 ) + ⋯ + ( r x − l x ) + ( r x − 0 ) = i + ∑ j = 1 x ( r j − l j ) (i-l_{1})+(r_{1}-l_{1})+(r_{1}-l_{2})+\dots+(r_{x}-l_{x})+(r_{x}-0)=i+\sum_{j=1}^{x}(r_{j}-l_{j}) ( i − l 1  ) + ( r 1  − l 1  ) + ( r 1  − l 2  ) + ⋯ + ( r x  − l x  ) + ( r x  − 0 ) = i + j = 1 ∑ x  ( r j  − l j  ) 
式中x = min  { l , r } x=\min\lbrace l,r \rbrace x = min { l , r } 
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 int  n;string s; cin >> n >> s; vector<int > a (n + 1 )  ;for  (int  i = 1 ; i <= n; i++) {    if  (s[i] == '<' ) a[i] = 1 ;     else  a[i] = -1 ; } vector<array<int , 2>> cnt (n + 1 );   vector<ll> l, r; l.push_back (0 ), r.push_back (0 ); for  (int  i = 1 ; i <= n; i++) {    cnt[i] = cnt[i - 1 ];     if  (s[i] == '<' ) {         cnt[i][0 ]++;         l.push_back (i);     }     else  {         cnt[i][1 ]++;         r.push_back (i);     } } auto  prel = l, prer = r;for  (int  i = 1 ; i < l.size (); i++) prel[i] += prel[i - 1 ];for  (int  i = 1 ; i < r.size (); i++) prer[i] += prer[i - 1 ];vector<ll> ans (n + 1 )  ;for  (int  i = 1 ; i < prel.size (); i++) {    ll suml = prel[i] - prel[cnt[i][0 ]];     ll sumr = prer[cnt[i - 1 ][1 ]] - 0 ;     ans[i] = (suml - sumr) * 2  + a[i] * i; } for  (int  i = prel.size (); i <= n; i++) {    ll suml = prel.back () - prel[cnt[i][0 ]];     ll sumr = prer[cnt[i - 1 ][1 ]] - prer[i - prel.size ()];     ans[i] = n + 1  + (suml - sumr) * 2  + a[i] * i; } for  (int  i = 1 ; i <= n; i++) {    cout << ans[i] << " \n" [i == n]; } 
题意  象棋中两个兵,谁会吃掉谁?
思路  考虑极左点和极右点。
1 2 3 4 5 6 7 8 9 10 11 12 13 scanf ("%d %d %d %d %d %d" , &h, &w, &x1, &y1, &x2, &y2);if  (x1 >= x2) { printf ("Draw\n" );} else  if  (x2 - x1 & 1 ) {     ll l1 = max (y1 - (x2-x1)/2 , 1 ), r1 = min (y1 + (x2-x1)/2 , w);     ll l2 = max (y2 - (x2-x1)/2 , 1 ), r2 = min (y2 + (x2-x1)/2 , w);     if  (l1 <= l2 + 1  && r1 >= r2 - 1 ) printf ("Alice\n" );     else  printf ("Draw\n" ); } else  {     ll l1 = max (y1 - (x2-x1)/2 , 1 ), r1 = min (y1 + (x2-x1)/2 , w);     ll l2 = max (y2 - (x2-x1-1 )/2 , 1 ), r2 = min (y2 + (x2-x1-1 )/2 , w);     if  (l2 <= l1 + 1  && r2 >= r1 - 1 ) printf ("Bob\n" );     else  printf ("Draw\n" ); } 
题意  求在半径为r r r 
思路  设( x , y ) (x,y) ( x , y ) d 2 = x 2 + y 2 > r 2 d^2=x^2+y^2>r^2 d 2 = x 2 + y 2 > r 2 d d d d 2 ⩾ r 2 + 1 d^2\geqslant r^2+1 d 2 ⩾ r 2 + 1 ( 1 , r ) (1,r) ( 1 , r ) d 2 = r 2 + 1 d^2=r^2+1 d 2 = r 2 + 1 d 2 d^2 d 2 r 2 + 1 r^2+1 r 2 + 1 ( 1 , r ) (1,r) ( 1 , r ) 
题意  在平面上的放置n n n 1 1 1 
思路 ⌈ n ⌉ − 1 = ⌊ n − 1 ⌋ \lceil\sqrt{n}\rceil-1=\big\lfloor\sqrt{n-1}\big\rfloor ⌈ n  ⌉ − 1 = ⌊ n − 1  ⌋ 
注意  直接使用 sqrt() 函数有精度问题,需要手写一个.
评注  乱搞是一种做 CF 思维题的好方法! 
在第四种数据中,输出结果为987654321 987654321 9 8 7 6 5 4 3 2 1 975461057789971042 975461057789971042 9 7 5 4 6 1 0 5 7 7 8 9 9 7 1 0 4 2 Θ ( 1 ) \Theta(1) Θ ( 1 ) 
打开计算器,很容易发现:98765432 1 2 + 1 = 975461057789971042 987654321^2+1=975461057789971042 9 8 7 6 5 4 3 2 1 2 + 1 = 9 7 5 4 6 1 0 5 7 7 8 9 9 7 1 0 4 2 n − 1 \sqrt{n-1} n − 1  
或者:⌊ 975461057789971042 ⌋ = 987654321 \lfloor\sqrt{975461057789971042}\rfloor=987654321 ⌊ 9 7 5 4 6 1 0 5 7 7 8 9 9 7 1 0 4 2  ⌋ = 9 8 7 6 5 4 3 2 1 ⌊ n ⌋ \lfloor\sqrt{n}\rfloor ⌊ n  ⌋ 
又或者:⌈ 975461057789971042 ⌉ − 1 = 987654321 \lceil\sqrt{975461057789971042}\rceil-1=987654321 ⌈ 9 7 5 4 6 1 0 5 7 7 8 9 9 7 1 0 4 2  ⌉ − 1 = 9 8 7 6 5 4 3 2 1 ⌈ n ⌉ − 1 \lceil\sqrt{n}\rceil-1 ⌈ n  ⌉ − 1 
显然,第一式不一定能得到整数解,由题意知答案为整数,所以是错的.把其他三组数据带进第二式,发现也有误.而第三式是都符合的.于是你可以快乐地A C \rm AC A C 
事实上,经过推导,正确答案也是⌈ n ⌉ − 1 \lceil\sqrt{n}\rceil-1 ⌈ n  ⌉ − 1 
题意  一个抢红包系统的规则:假如现在有w w w [ 0 , w ] [0,w] [ 0 , w ] x x x w w w n n n k k k 1 0 9 + 7 10^9+7 1 0 9 + 7 思路  答案为w 2 k   m o d   1 0 9 + 7 \displaystyle\frac{w}{2^k}\bmod10^9+7 2 k w  m o d 1 0 9 + 7 题意  将尺寸为k × 1 k \times 1 k × 1 1 × k   ( k ≥ 2 ) 1 \times k~(k \geq 2) 1 × k   ( k ≥ 2 ) n × m n \times m n × m 思路 n ⋅ ⌊ m 2 ⌋ \displaystyle n\cdot\lfloor\frac m2\rfloor n ⋅ ⌊ 2 m  ⌋