出题人题解 | #Tachibana Kanade Loves Game#
Tachibana Kanade Loves Game
https://ac.nowcoder.com/acm/problem/23368
原题解链接:https://ac.nowcoder.com/discuss/173818
简单的数学题。
首先,你需要注意到题面种“若存在,则会使的你的血量减少 ”这句话的含义,是“如果存在,那么血量减”,因此无论有多少个 满足 ,你的血量都只会减少
考虑时,你开局就死了,因此答案一定为
考虑,即你不能选择任何会触发反击魔咒的武器,即你能够选择的数,不是中任何一个数的倍数。当 时,注意到我们不需要考虑任何情形。否则,考虑任意一个数,若其不为素数,则其一定有真素因子,若,则,因此我们只需要考虑的全体素数构成的集合,不妨记其为 ,则显然答案为: 然而这个式子难以处理,因此我们重新考虑后面的谓词表达式。记然而这个式子难以处理,因此我们重新考虑后面的谓词表达式。记,那么如果,那么如果,都有,都有,那么一定有,那么一定有,反之亦然。
结论1:,都有的充要条件为
证明:必要性是显然的。
充分性:假设,那么一定有,设,则一定存在使得 ,即,与条件矛盾。
因此,我们便可以计算出我们能造成的总伤害: 预处理出的,这个式子就可以通过枚举的因子计算完成。由于为个不同素数的乘积,因此它的因子个数为。时间复杂度,考虑到可以轻松通过此题
考虑,我们会发现,我们可以使用次会触发反击魔咒的武器,因此总伤害即为(要对 取的原因是每种武器只能用次,最多只能造成 点伤害)
最后,我们只需要判定输出,否则输出即可
#include <algorithm>
#include <cstdio>
#include <iostream>
#include <cstdlib>
#include <cmath>
#include <cassert>
constexpr int maxn = 10000000;
constexpr int mod = 20050117;
long long mu[maxn], b[maxn], pri[] = {0, 2, 3, 5, 7, 11, 13, 17, 19, 23, 29}, cnt, d[10005], size, T;
int table[] = {0, 0, 1, 2, 2, 3, 3, 4, 4, 4, 4, 5, 5, 6, 6, 6, 6, 7, 7, 8, 8, 8, 8 };
inline char nc()
{
static char buf[1000000], *p1 = buf, *p2 = buf;
return p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, 1000000, stdin), p1 == p2) ? EOF : *p1++;
}
inline long long read()
{
long long res = 0;
char ch = nc();
while (!isdigit(ch)) ch = nc();
while (isdigit(ch)) res = res * 10 + ch - 48, ch = nc();
return res;
}
int main()
{
d[0] = d[1] = 1;
mu[0] = mu[1] = 1;
for (int i = 1; i <= 8; ++i)
{
for (int k = 1; k <= size; ++k)
{
d[k + size] = d[k] * pri[i];
mu[d[k + size]] = -mu[d[k]];
}
d[size = (size << 1) + 1] = pri[i];
mu[pri[i]] = -1;
}
T = read();
while (T--)
{
long long k = read(), q = read(), n = read(), m = read();
if (k == 0)
{
puts("QAQ");
continue;
}
long long s, x, y, ans = 0;
x = 1, y = n, s = m;
s = table[s];
--x;
size = (1 << s) - 1;
for (int i = 0; i <= size; ++i)
ans = (ans + mu[d[i]] * (y / d[i] - x / d[i]));
ans = std::min(n, ans + k - 1);
if (ans >= q) puts("Yes");
else puts("QAQ");
}
return 0;
}