题目链接:https://ac.nowcoder.com/acm/problem/213147
到主站看:https://blog.csdn.net/weixin_43346722/article/details/109390755
题目
Alice 和 Bob 各带来一个正多边形卡片。
Alice 的卡片是边长为 的正
边形,Bob 的卡片是边长为
的正
边形。
Alice 和 Bob 将两张卡片摆放在一起,其中两张卡片并不重叠,并且有至少一个公共顶点和一条公共边。
Alice 喜欢旋转,因此她沿 Bob 的卡片顺时针旋转自己的多边形。
旋转的中心点是多边形公共边上一点,且旋转过程中两张卡片不重叠。
Alice 想知道,在旋转多少次过后,Alice 的正多边形会回到原位置。
输入
一行,四个整数 ,含义如题目描述所述。
输出
一行,一个数 ,表示 Alice 旋转的次数。
样例输入1
2 4 3 4
样例输出1
8
样例解释1
前两次操作如下图所示:
样例输入2
3 4 4 4
样例输出2
24
样例输入3
2020 1024 2021 1025
样例输出3
828200
数据范围
对于 的数据,
,且
;
对于另外 的数据,
,
,且
;
对于另外 的数据,
是
的倍数;
对于 的数据,
,
,
。
思路
这道题是一道数学题吧。
就是把普通的翻滚和在角落的翻滚分开讨论要弄多少次。
首先可以发现我们完全不用管 Alice 的多边形是多少边的。
普通的翻滚就是把 Bob 的多边形拉成一条圆,问要滚滚多少次才能滚回原来的点。
角落的翻滚就是先求出翻转到 Alice 的多边形与 Bob 的多边形的接壤的边接壤在 Bob 的多边形的最左边时,要到多少次角落,然后有多少次要转的。
(有一次不用转,就是最后一次)
比赛时
想到是数论,但是不知道要分开两个情况讨论。
然后搞了一个奇奇怪怪的东西(当时还觉得能过
弄了个 分。
好像是没有处理转角落中不用转的那一次。(好像
代码
#include<cstdio> #define ll long long using namespace std; ll a, m, b, n, line, linetime, turn, turntime; ll gcd(ll x, ll y) { if (!y) return x; return gcd(y, x % y); } int main() { scanf("%lld %lld %lld %lld", &a, &m, &b, &n); line = a * (n * b) / gcd(a, (n * b));//不转角要走多少次 linetime = line / a; turn = a * b / gcd(a, b); turntime = line / turn * (turn / b - 1);//要转角多少次 printf("%lld", linetime + turntime); return 0; }