C. Candy Store

发布时间 2023-03-27 23:09:33作者: onlyblues

C. Candy Store

The store sells $n$ types of candies with numbers from $1$ to $n$. One candy of type $i$ costs $b_i$ coins. In total, there are $a_i$ candies of type $i$ in the store.

You need to pack all available candies in packs, each pack should contain only one type of candies. Formally, for each type of candy $i$ you need to choose the integer $d_i$, denoting the number of type $i$ candies in one pack, so that $a_i$ is divided without remainder by $d_i$.

Then the cost of one pack of candies of type $i$ will be equal to $b_i \cdot d_i$. Let's denote this cost by $c_i$, that is, $c_i = b_i \cdot d_i$.

After packaging, packs will be placed on the shelf. Consider the cost of the packs placed on the shelf, in order $c_1, c_2, \ldots, c_n$. Price tags will be used to describe costs of the packs. One price tag can describe the cost of all packs from $l$ to $r$ inclusive if $c_l = c_{l+1} = \ldots = c_r$. Each of the packs from $1$ to $n$ must be described by at least one price tag. For example, if $c_1, \ldots, c_n = [4, 4, 2, 4, 4]$, to describe all the packs, a $3$ price tags will be enough, the first price tag describes the packs $1, 2$, the second: $3$, the third: $4, 5$.

You are given the integers $a_1, b_1, a_2, b_2, \ldots, a_n, b_n$. Your task is to choose integers $d_i$ so that $a_i$ is divisible by $d_i$ for all $i$, and the required number of price tags to describe the values of $c_1, c_2, \ldots, c_n$ is the minimum possible.

For a better understanding of the statement, look at the illustration of the first test case of the first test:

Let's repeat the meaning of the notation used in the problem:

$a_i$ — the number of candies of type $i$ available in the store.

$b_i$ — the cost of one candy of type $i$.

$d_i$ — the number of candies of type $i$ in one pack.

$c_i$ — the cost of one pack of candies of type $i$ is expressed by the formula $c_i = b_i \cdot d_i$.

Input

Each test contains multiple test cases. The first line contains the number of test cases $t$ ($1 \le t \le 100\,000$). Description of the test cases follows.

The first line of each test case contains a single integer $n$ ($2 \le n \le 200\,000$) — the number of types of candies.

Each of the next $n$ lines of each test case contains two integers $a_i$ and $b_i$ ($1 \le a_i \le 10^9$, $1 \le b_i \le 10\,000$) — the number of candies and the cost of one candy of type $i$, respectively.

It is guaranteed that the sum of $n$ over all test cases does not exceed $200\,000$.

Output

For each test case, output the minimum number of price tags required to describe the costs of all packs of candies in the store.

Example

input

5
4
20 3
6 2
14 5
20 7
3
444 5
2002 10
2020 2
5
7 7
6 5
15 2
10 3
7 7
5
10 1
11 5
5 1
2 2
8 2
6
7 12
12 3
5 3
9 12
9 3
1000000000 10000

output

2
1
3
2
5

Note

In the first test case, you can choose $d_1 = 4$, $d_2 = 6$, $d_3 = 7$, $d_4 = 5$. Then the cost of packs will be equal to $[12, 12, 35, 35]$. $2$ price tags are enough to describe them, the first price tag for $c_1, c_2$ and the second price tag for $c_3, c_4$. It can be shown that with any correct choice of $d_i$, at least $2$ of the price tag will be needed to describe all the packs. Also note that this example is illustrated by a picture in the statement.

In the second test case, with $d_1 = 4$, $d_2 = 2$, $d_3 = 10$, the costs of all packs will be equal to $20$. Thus, $1$ price tag is enough to describe all the packs. Note that $a_i$ is divisible by $d_i$ for all $i$, which is necessary condition.

In the third test case, it is not difficult to understand that one price tag can be used to describe $2$nd, $3$rd and $4$th packs. And additionally a price tag for pack $1$ and pack $5$. Total: $3$ price tags.

 

解题思路

  先给出比赛时想到的做法。思路比较暴力,代码也很长。

  对于总数量为$a_i$的糖果,第$i$种糖果的每一小包中允许的数量为$a_i$的约数。因此容易想到直接分解得到每个$a_i$的所有约数,然后每个约数都乘上$b_i$,那么就得到第$i$种糖果允许存在的所有代价。最后从前往后枚举所有糖果并尽可能取合法代价的交集,这部分当时比赛没想到,后面再细说。

  首先每个$a_i$最大能够取到${10}^9$,如果直接暴力分解约数那么时间复杂度就是$O(\sqrt{{10}^9} \cdot n)$,肯定会TLE。这个时候我们就退而求次,先筛出$\sqrt{{10}^9}$内的所有素数,然后对$a_i$分解质因数,由于在${10}^9$内一个数最多有$1344$个约数,因此可以直接通过质因数来暴搜找到$a_i$的所有约数,那么时间复杂度就降到了$O \left( n \cdot \left( \frac{\sqrt{{10}^9}}{\ln{\sqrt{{10}^9}}} + 1344 \right) \right)$级别,其中$\sqrt{{10}^9}$内的素数个数为$3400$个左右,因此计算量大约是${10}^8$级别,时间限制为$3s$感觉不会T(?)。

  其实按照我现在这种做法在cf上面不会T(2023-03-27),但为了保证严谨性,我特意构造了组极限数据跑了下,然后我成功把自己给hack了。构造的数据很简单,就是$a = 735134400, \ b = 1$和$a = 3, \ b = 1$共交替出现$2 \times {10}^5$次就可以了。其中$735134400$有$1344$个约数,且$3 \nmid 735134400$。

  但还是继续说一下做法吧。现在给出了种还可以的分解质因数的方法,接下来就是如何选代价的问题了。假设第$i$种糖果的代价为集合$c_i$,如果第$i+1$种糖果想与第$i$种糖果的代价一样,那么很明显能选的代价为两个集合$c_i$与$c_{i+1}$的交集。以此类推,如果第$l$种糖果到第$r$种糖果的代价都相同,那么就要满足$\bigcap\limits_{i = l}^{r} c_i \ne \varnothing$。

  因此我们可以从前往后枚举$i$,对于第$i$种糖果每次求$c_i$与$c_{i-1}$的交集(此时的$c_{i-1}$是$c_l$到$c_{i-1}$的交集),如果得到的结果不为空,那么说明第$l \sim i$种糖果可以有相同的代价。如果直接暴力求两个集合的交集那么时间复杂度是$O(|c_{i}| \cdot |c_{i-1}|)$,一共要求$n$个集合的交集,必定会超时。因此在求交集的部分需要优化。

  注意到对于$\forall x \in c_{i} \cap c_{i-1}$必定满足$x \mid b_i$且$\tfrac{x}{b_i} \mid a_i$,因此我们只需要枚举$c_{i-1}$的每一个元素$x$,如果$x$满足这两个条件那么我们就保留$x$,时间复杂度就降到了$O(n \cdot |c_{i-1}|) \approx O(1344 \cdot n)$。可以发现甚至第$i$种糖果的代价都不需要求了(即不需要对$a_i$分解约数)。而如果在这个过程中没有选到任何元素,即交集为空,我们才需要求第$i$种糖果的代价$c_i$。

  TLE代码如下:

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 
 4 typedef long long LL;
 5 
 6 const int N = 2e5 + 10;
 7 
 8 int primes[N], cnt;
 9 bool vis[N];
10 int a[N], b[N];
11 vector<vector<int>> fs;
12 vector<LL> c[N];
13 
14 void get_prime(int n) {
15     for (int i = 2; i <= n; i++) {
16         if (!vis[i]) primes[cnt++] = i;
17         for (int j = 0; primes[j] <= n / i; j++) {
18             vis[primes[j] * i] = true;
19             if (i % primes[j] == 0) break;
20         }
21     }
22 }
23 
24 void dfs(int k, int u, int prod) {
25     if (u == fs.size()) {    // 找到约数prod
26         c[k].push_back(1ll * prod * b[k]);    // 记录第k种糖果所有可能的代价
27         return;
28     }
29     int t = 1, p = fs[u][0], s = fs[u][1];
30     for (int i = 0; i <= s; i++) {
31         dfs(k, u + 1, prod * t);
32         t *= p;
33     }
34 }
35 
36 void get(int k) {
37     fs.clear();
38     int t = a[k];
39     for (int i = 0; primes[i] <= t / primes[i]; i++) {    // 质因数分解
40         int p = primes[i];
41         if (t % p == 0) {
42             int s = 0;
43             while (t % p == 0) {
44                 t /= p;
45                 s++;
46             }
47             fs.push_back({p, s});
48         }
49     }
50     if (t > 1) fs.push_back({t, 1});
51     dfs(k, 0, 1);    // 暴搜出a[k]的所有约数
52 }
53 
54 void solve() {
55     int n;
56     scanf("%d", &n);
57     for (int i = 0; i < n; i++) {
58         scanf("%d %d", a + i, b + i);
59         c[i].clear();
60     }
61     get(0);    // 求第0种糖果的所有可能代价
62     int ret = 1;    // 答案至少是1
63     for (int i = 1; i < n; i++) {
64         for (auto &x : c[i - 1]) {    // 求交集
65             if (x % b[i] == 0 && a[i] % (x / b[i]) == 0) c[i].push_back(x);
66         }
67         if (c[i].empty()) {    // 交集为空
68             ret++;    // 需要的代价种类+1
69             get(i);    // 求第i种糖果的所有可能代价
70         }
71     }
72     printf("%d\n", ret);
73 }
74 
75 int main() {
76     get_prime(N - 1);    // 筛出sqrt(1e9)内的质数,用于质因数分解
77     int t;
78     scanf("%d", &t);
79     while (t--) {
80         solve();
81     }
82     
83     return 0;
84 }

  下面给出正解,是真想不到。

  假设第$l$种糖果到第$r$种糖果的代价一样,令$c_i = d_i \cdot b_i$,即有$c_l = c_{l+1} = \cdots = c_r = x$,其中$d_i \mid a_i$。

  那么可以发现对于$\forall i \in [l,r]$,$b_i$是$x$的一个因子,即$x$是$b_i$的倍数,因此必然有$\operatorname{lcm} \left[ b_l, \ldots, b_r \right] \mid x$。

  同时由于$d_i \mid a_i$,因此有$d_i \cdot b_i \mid a_i \cdot b_i$,即$x$是$a_i \cdot b_i$的一个因子,这就等价于$x \mid \gcd(c_l, \ldots,c_{r})$。

  因此如果有$c_l = c_{l+1} = \cdots = c_r$,那么必然有$\operatorname{lcm} \left[ b_l, \ldots, b_r \right] \mid \gcd(a_l \cdot b_l, \ldots, a_r \cdot b_r)$,反过来也成立。

  然后从前往后枚举,维护连续序列的最大公约数$d$和最小公倍数$m$,贪心地选择,即如果满足$m \mid d$则使用同一个代价,而如果$m \nmid d$则说明需要开另外一个代价。

  AC代码如下,时间复杂度为$O(n \cdot \log{{10}^9})$:

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 
 4 typedef long long LL;
 5 
 6 LL gcd(LL a, LL b) {
 7     return b ? gcd(b, a % b) : a;
 8 }
 9 
10 LL lcm(LL a, LL b) {
11     return a / gcd(a, b) * b;
12 }
13 
14 void solve() {
15     int n;
16     scanf("%d", &n);
17     LL d = 0, m = 1;
18     int ret = 1;
19     while (n--) {
20         LL a, b;
21         scanf("%lld %lld", &a, &b);
22         m = lcm(m, b);
23         d = gcd(d, a * b);
24         if (d % m) {
25             ret++;
26             d = a * b, m = b;
27         }
28     }
29     printf("%d\n", ret);
30 }
31 
32 int main() {
33     int t;
34     scanf("%d", &t);
35     while (t--) {
36         solve();
37     }
38     
39     return 0;
40 }

 

参考资料

  Codeforces Round 860 (Div. 2) A~E:https://zhuanlan.zhihu.com/p/617245703

  Editorial of Codeforces Round 860 (Div. 2):https://codeforces.com/blog/entry/114208