0%

Educational Codeforces Round 187 (Rated for Div. 2)-CF-Edu-187-D. Divisibility Game(较大数据量下 vector 套 vector 的调和级数因数分解会出问题)(觉得有点把握不住,就上 int128,一般就比较难卡掉了)(在高版本 C++,要自己定义 lcm 函数就写 lcm128 什么的,就写 lcm 可能给你直接调 std::lcm)

题目大意

题目大意

Alice 和 Bob 在玩一个游戏。给定两个数组:包含 nn 个元素的数组 aa 和包含 mm 个元素的数组 bb

两人轮流进行操作,Alice 先手。在每个回合中,玩家需要从数组 aa 中选择一个数字 xx,并从数组 bb 中选择一个数字 yy

  • Alice 的规则:选择的 yy 必须能被 xx 整除。

  • Bob 的规则:选择的 yy 必须不能被 xx 整除。

选定 xxyy 后,yy 会从数组 bb 中被移除(如果数组中存在多个相同的 yy,只移除其中一个),而 xx 仍然保留在数组 aa 中。无法进行合法操作(即无法选出满足自身规则的 xxyy)的玩家将输掉游戏。

假设双方都采取最优策略,请判断谁会赢得游戏。

输入格式

第一行包含一个整数 tt1t1041 \le t \le 10^4),表示测试用例的数量。

对于每个测试用例:
第一行包含两个整数 nnmm1n,m1061 \le n, m \le 10^6)。
第二行包含 nn 个整数 aia_i1ain+m1 \le a_i \le n+m),表示数组 aa 的元素。
第三行包含 mm 个整数 bib_i1bin+m1 \le b_i \le n+m),表示数组 bb 的元素。

保证所有测试用例中 nn 的总和以及 mm 的总和均不超过 10610^6

输出格式

对于每个测试用例,输出获胜者的名字:如果 Alice 赢,输出 Alice;如果 Bob 赢,输出 Bob

样例输入

1
2
3
4
5
6
7
8
9
10
3
9 3
3 2 4 2 2 4 4 2 4
6 7 12
10 3
3 2 5 4 2 5 3 4 4 4
10 7 13
1 5
1
1 2 3 4 5

样例输出

1
2
3
Alice
Bob
Alice

样例解释

对于第一个测试用例,Alice 的获胜过程如下:

  1. Alice 的回合:选择 x=3,y=6x=3, y=666 能被 33 整除)。操作后 66 从数组 bb 中移除,此时 b=[7,12]b=[7, 12]

  2. Bob 的回合:选择 x=3,y=7x=3, y=777 不能被 33 整除)。Bob 在这个回合只能选择 y=7y=7,因为对于 y=12y=12,数组 aa 中找不到任何不能整除它的 xx。操作后 77 从数组 bb 中移除,此时 b=[12]b=[12]

  3. Alice 的回合:选择 x=4,y=12x=4, y=121212 能被 44 整除)。操作后 1212 从数组 bb 中移除,此时数组 bb 变为空。

  4. Bob 的回合:数组 bb 已经为空,Bob 无法进行任何操作,因此 Bob 输掉游戏,Alice 获胜。

思路讲解

OK,我们说回来。这个D为什么交了5发还是没过呢?主要是因为就是这个D,它的数据量比较大。使用Victor victor或者victor的这种调和级数写法呢,它这个时间会超。可以使用vis 数组标记所有 a 的倍数。这样子可以避免卡常。

1
2
3
4
5
6
7
8
9
10
ll cnt_un_divide=0,cnt_all_divide=0;
vector<char> vis(N+M+2);
for (auto a:A) {
for (ll i=1;i<=N+M;++i) {
if (i*a>N+M) {
break;
}
vis[i*a]=true;
}
}

然后为什么标题里面提了不要用 while 循环?是因为涉及累加的逻辑(在 D 的对拍暴力程序当中),直接 continue 以后,while 循环的这个累加就崩掉了。

AC代码

AC
https://codeforces.com/contest/2203/submission/364454955

心路历程(WA,TLE,MLE……)

image

后面还被系统测试阴了一手,把这个LCM改成128,用INT128就可以了,这个叫什么,当时其实我就知道这里应该是会有点问题的,想用这个128嘛,但是可能还是犹豫还是犹豫了。

1
2
3
4
i128 lcm128(i128 a,i128 b) {
i128 res=a*b/__gcd(a,b);
return res;
}