题意:一天又H小时每小时M分钟,给定夹角α=(2 * π * A)/(H*M),求一天中分针和时针夹角小于等于α的分钟数(只考虑整点分钟不考虑秒)
思路:
稍微分析一下题目就很容易知道几个条件
分针角速度 w1=2π/M
时针角速度 w2=2π/(H*M)
总共的路程按照分钟来做单位就是H*M分钟。
将角速度变换为线速度,也比较容易的能想象出一维数轴上,是一个速度快的物体和一个速度慢的物体在做追及相遇问题。并且快的物体每次到终点就自动回到起点上,慢的物体到终点后停止游戏。
按照相对速度来看,实际上是相对速度走的路程在夹角α对应的弧长内,那么这段路程就是合法路程,进而能换算出合法的时间。
假设当前时间是t,显然有t*(v1-v2)%HM<=α*R(其中R是半径)
展开是:t*((2 * π * R)/M-(2 * π * R)/(HM))%HM<=α*R
约分后可得t*(H-1)%HM<=A
此时,如果你的HM要是比较小,你完全可以枚举t(因为t的取值范围就是HM,因为算的是一天的)但是题目中HM给的范围过大(1e18)考虑优化。
如果在不等式中没有了(H-1),那么t%HM<=A的合法的t的数量就可以直接算了,显然是2*A+1(当然不算A大于等于HM/2的情况).所以想办法怎么约掉这个东西让公式变得不需要枚举。
对于取模的情况考虑到了剩余系定理三
若a,b,c为任意3个整数,m为正整数,且GCD(m,c)=1,则当ac≡bc(mod m)时,有a≡b(mod m)
(所以可以看成a和b同时乘上了一个c)
那么我们要怎么去找一个c让H-1和H*M取模于m同余并且m和c互质呢?
考虑到GCD(H-1,HM)
设c=GCD(H-1,HM)。
原公式就可以利用黄色的定理变成
t*(H-1)/c%HM/c<=A
又因为H-1被除了个c所以为了保证平衡,A也要除c
最后公式变为
t*(H-1)/c%HM/c<=A/c
此时(H-1)/c可以视为1
所以公式进一步变化为
t*%HM/c<=A/c
所以推出一半的解就是A/c,它包括了1,2,3,…,A/C这些分钟时刻。
然后算上另一半对称的和0的情况就是2*(A/c)+1
由于你在推导公式的时候将HM缩放为HM/c所以最后还需要将答案缩放回去
最终答案就是:c*(2*(A/c)+1)(当且仅当A<HM/2)
当A>=HM/2时,答案显然为H*M
#include <iostream>
#include <algorithm>
#define ll long long
using namespace std;
int main(){
ll h, m, a;
cin >> h >> m >> a;
ll g = __gcd(h - 1, h * m);
cout << min(m * h, g * (2 * (a / g) + 1)) << endl;
return 0;
}