題解 GZOI2023D2B【乒乓球】

caijianhong發表於2024-09-09

4s, 512M

題目描述

Alice 和 Bob 在打乒乓球,乒乓球比賽的規則是這樣的:一場比賽中兩位選手將進行若干局比賽,選手只需要贏得 \(X\) 局比賽就宣告其勝利;每局比賽中兩位選手將進行若干盤比賽,選手只需要贏得 \(Y\) 盤比賽就宣告其勝利;每盤比賽中兩位選手將進行乒乓球對決,有且僅有一位選手能被宣告勝利。

你作為 Alice 的朋友觀戰了他們的比賽,發現 Alice 贏了 \(P\) 盤比賽,Bob 贏了 \(Q\) 盤比賽,最後 Alice 取得了整場比賽的勝利。但是你已經忘了 \(X, Y\) 的具體取值,請問有多少種 \(X, Y\) 使得能存在一種方案滿足你記錄下的資訊。

輸入格式

第一行兩個正整數 \(P, Q\)

輸出格式

第一行一個正整數表示方案數。

樣例

7 5
4

樣例零中,\((X, Y)\) 的所有可能取值為 \((1, 7), (2, 3), (3, 2), (7, 1)\)

554 454
1226

資料範圍

  • 對於 \(30\%\) 的資料,\(P, Q\leq 10^3\)
  • 對於 \(50\%\) 的資料,\(P, Q\leq 10^6\)
  • 對於 \(70\%\) 的資料,\(P, Q\leq 10^{12}\)
  • 另外有 \(10\%\) 的資料,\(Q=0\)
  • 對於 \(100\%\) 的資料,\(P, Q\leq 10^{14}\),並請注意 \(X, Y\) 均應為正整數。

solution

設 Bob 贏下了 \(Z\) 局比賽,因為 Bob 贏的局數會影響 Alice 可以贏的局數。可以列出以下不等式:

\[\begin{aligned} Z&<X\\ XY&\leq P\leq XY+Z(Y-1)\\ ZY&\leq Q\leq ZY+X(Y-1) \end{aligned} \]

觀察到在 \(ZY\leq Q\) 的限制下,將 \(Z\) 增大一定是不劣的,所以一定有

\[Z=\min(X - 1, \left\lfloor Q/Y\right\rfloor) \]

因為 \(XY\leq P\),所以可以調和級數列舉 \(X, Y\),獲得 \(50\) 分。

\(Z\) 的取值分類討論。

Z = floor(Q / Y)

對於 \(ZY\leq Q\leq ZY+X(Y-1)\),這自然滿足,因為 \(Q-ZY<Y\),所以 \(Q-ZY\leq Y - 1\leq X(Y - 1)\)

對於 \(XY\leq P\leq XY+Z(Y-1)=XY+ZY-Z\) 以及 \(Z\leq X-1\) 可以寫出:

\[\max(Z+1, \left\lceil(P+Z)/Y\right\rceil-Z)\leq X\leq \left\lfloor P/Y\right\rfloor \]

三次整除分塊解決。先 \(\left\lfloor Q/Y\right\rfloor\) 確定 \(Z\) 以及 \(Y\) 對應區間。然後獲得 $ \left\lceil(P+Z)/Y\right\rceil$(注意向上取整,或者寫為 $ \left\lfloor(P+Z-1)/Y\right\rfloor+1$)以及 $ \left\lfloor P/Y\right\rfloor$。

Z = X - 1

對於 \(X-1<\left\lfloor Q/Y\right\rfloor\) (等號在上一種情況討論了)可以推出 \(X\leq Q/Y\) 所以 \(XY\leq Q\)

對於 \(ZY\leq Q\leq ZY+X(Y-1)\),左邊自然滿足,右邊 \(Q\leq 2XY-X-Y\)

對於 \(XY\leq P\leq XY+Z(Y-1)=2XY-X-Y+1\),其實發現兩條不等式很類似。感受一下:

\[\begin{aligned} &XY\leq P\leq 2XY-X-Y+1\\ &XY\leq Q\leq 2XY-X-Y\\ \end{aligned} \]

兩個變數的地位等同,不妨:

\[X\leq\left\lfloor\min(P, Q)/Y\right\rfloor \]

後面這個部分,\(P, Q\) 對稱,設 \(R=\max(P - 1, Q)\),然後

\[R\leq 2XY-X-Y \]

\(X\) 為主元,求出 \(X\) 的範圍。

\[R+Y\leq (2Y-1)X \]

所以

\[X\geq\left\lceil \frac{R+Y}{2Y-1}\right\rceil \]

\[X\geq\left\lfloor \frac{R+Y-1}{2Y-1}\right\rfloor+1 \]

感受一下,右邊的值域比較小,嘗試對 \(Y\) 進一步整除分塊。令 \(V=\left\lfloor\frac{R+Y-1}{2Y-1}\right\rfloor\)。求出使得那一坨東西 \(=V\)\(Y\) 的範圍。

\[\begin{aligned} V&\leq (R+Y-1)/(2Y-1)\\ 2VY-V&\leq R+Y-1\\ Y&\leq \frac{R+V-1}{2V-1}\\ Y&\leq \left\lfloor\frac{R+V-1}{2V-1}\right\rfloor\\ \end{aligned} \]

至此所有問題都解決了。時間複雜度 \(O(\sqrt P+\sqrt Q)\),具體幾倍常數不知道。

code

正確性未知
#include <bits/stdc++.h>
using namespace std;
#ifdef LOCAL
#define debug(...) fprintf(stderr, ##__VA_ARGS__)
#else
#define endl "\n"
#define debug(...) void(0)
#endif
using LL = long long;
LL p, q, ret;
int main() {
#ifndef LOCAL
  cin.tie(nullptr)->sync_with_stdio(false);  
#endif
  cin >> p >> q;
  for (LL l = 1, r; l <= p; l = r + 1) {
    LL z = q / l, pz1 = p + z - 1;
    r = p / (p / l);
    if (l <= pz1) r = min(r, pz1 / (pz1 / l));
    if (z) r = min(r, q / z);
    ret += (r - l + 1) * max(0ll, p / l - max(z + 1, pz1 / l + 1 - z) + 1);
  }
  for (LL l = 1, r; l <= min(p, q); l = r + 1) {
    r = min(p, q) / (min(p, q) / l);
    LL v = (max(p - 1, q) + l - 1) / (2 * l - 1);
    if (v) r = min(r, (max(p - 1, q) + v - 1) / (2 * v - 1));
    ret += (r - l + 1) * max(0ll, min(p, q) / l - v);
  }
  cout << ret << endl;
  return 0;
}