时间限制 | 内存限制 |
---|---|
1000 ms |
65536 KB |
# 题目描述
数学之神讨厌素数,「暮念」因为证明了 “任一大于 的偶数都可写成两个素数之和” 而惹恼了数学之神,被流放到了一个名为「悲寂瀛」的异世界,他的好朋友「瑄瑄」也因受牵连而被一同流放。该世界被分割成无限个独立的空间,每个空间都以坐标点 来标记,「暮念」被关押在坐标为 的空间「CVBB」,而「瑄瑄」被困在遥远的未知空间「QLV」中,她所在的坐标为 。各空间之间存在着时空乱流,阻止犯人穿越,但好在「暮念」掌握了一系列蕴含时空法则的秘术,可以突破乱流干扰,从一个坐标移动到另一个坐标。秘术介绍如下:
秘术 1:从 移动到 ;
秘术 2:从 移动到 ;
秘术 3:从 移动到 ;
秘术 4:从 移动到 。
其中 是被数学之神诅咒过的素数。
现在「暮念」需要施展有限次秘术,从空间「CVBB」移动到空间「QLV」以解救「瑄瑄」,请你帮助他判断能否完成解救任务。
# 输入格式
本题有多组数据。
第一行输入 个整数 ,表示数据组数,保证 。
接下来输入 行,每行 个整数 ,保证 为素数,。
# 输出格式
对于每组数据,输出一行:
如果能,输出 iloveyou
;
如果不能,输出 seeyouagain
。
# 输入样例
3 | |
2 6 9 | |
2 4 7 | |
7 14 21 |
# 输出样例
seeyouagain | |
iloveyou | |
iloveyou |
# 样例解释
第一组数据:无法通过秘术从 移动到 。
第二组数据:可以通过秘术按以下路径到达:。
第三组数据:可以通过秘术按以下路径到达:。
# 题解:最大公因数
为什么会想到最大公因数?注意到题目里的 “秘术”,加加减减让人联想到辗转相减 / 除法求最大公因数,而乘法操作相当于将最大公因数翻 的次幂倍。
想到这里就可以开始写题了,赛场上谁有时间给你严格证明这个结论,以下是对这个结论的严格证明:
必要性:对于前两个秘术, 保持不变;对于后两个秘术, 不变或变为原来的 倍。所以若一个点能从点 到达,则必然有 。
充分性:若一个点 满足 ,下归纳证明其必然能从点 到达。
-
当 时, 即为 ,显然可以到达。
-
假设对于所有满足 且 的点均能从点 到达,证明对于所有满足 且 的点也可到达,其中 。
-
若 和 中至少有一个为 的倍数,不妨设 为 的倍数,根据归纳假设,点 可到达,故点 可到达。
-
若 和 均不为 的倍数且 ,不妨设 ,存在 ,使得 。构造点 ,则 且 ,根据归纳假设,点 可到达,故点 也可以到达。
-
若 均不为 的倍数且 ,则 ,此时 与 的假设矛盾。
-
综上所述,对于给定点 ,只需通过辗转相除法求出 ,再判断 是否为 的 次幂即可。
时间复杂度:,其中 为测试数据组数。
参考代码:
#include <stdio.h> | |
#include <stdbool.h> | |
typedef long long ll; | |
ll gcd(ll a, ll b) | |
{ | |
return b ? gcd(b, a % b) : a; | |
} | |
int main() | |
{ | |
// freopen("I.in", "r", stdin); | |
// freopen("I.out", "w", stdout); | |
int T; | |
scanf("%d", &T); | |
while (T -- ) | |
{ | |
int a; | |
ll r, s; | |
scanf("%d%lld%lld", &a, &r, &s); | |
ll g = gcd(r, s); | |
bool flag = true; | |
while (g > 1) | |
{ | |
if (g % a != 0) | |
{ | |
flag = false; | |
break; | |
} | |
g /= a; | |
} | |
if (flag) | |
puts("iloveyou"); | |
else | |
puts("seeyouagain"); | |
} | |
return 0; | |
} |