题目
题目链接:https://www.luogu.com.cn/problem/P3409
一开始读题了,一下所有 (m) 和 (p) 与题目中意思对调。
话说,在一个学期共有 (n) 个值日班长,其中 A 是第 (p) 个值日班长,共有 (m) 个值周班长,B 是第 (q) 个值周班长。假设不考虑假期及其他额外上课休假,以及重排值日班长值周班长,即永远每周上 5 天休息 2 天,且这个学期永远不会结束。请问这学期第几天会第一次遇上 A 是值日班长且 B 是值周班长,若永远不会输出 Orz mgh!!!。
(n,mleq 10^9)。
思路
被卡了 long long 调了好久最后看题解都是用了 int128 的。。。
考虑设值日班长轮了 (x) 轮,值周班长轮了 (y) 轮,显然就是要求最小的非负整数解 (x,y) 满足:
[nx+p=5(my+q)+k
]
其中 (k) 是这周还有多少天结束,显然可以枚举。
对于每一个枚举的 (k),直接把式子化成
[nx-5my=5q+k-p
]
直接解出 (x,y) 的最小非负整数解,答案即为 (nx+p)。
时间复杂度 (O(Tlog n))。
代码
#include <bits/stdc++.h>
using namespace std;
typedef __int128 ll;
const ll Inf=9223372036854775807LL;
ll ans,n,m,p,q;
long long _,__,___,____;
/*
ll read()
{
ll d=0; char ch=getchar();
while (!isdiigt(ch)) ch=getchar();
while (isdigit(ch)) d=(d<<3)+(d<<1)+ch-48,ch=getchar();
return d;
}
*/
void write(ll x)
{
if (x>9) write(x/10);
putchar(x%10+48);
}
ll exgcd(ll a,ll b,ll &x,ll &y)
{
if (!b) { x=1; y=0; return a; }
ll d=exgcd(b,a%b,x,y),t=x; x=y; y=t-a/b*y;
return d;
}
int main()
{
while (scanf("%lld%lld%lld%lld",&_,&__,&___,&____)!=EOF)
{
n=_; p=__; m=___; q=____; // 疯了
p--; q--; ans=-1;
for (ll k=0;k<=4;k++)
{
ll x,y,d=exgcd(n,5*m,x,y),l=(n*5*m)/d/n;
if ((5*q+k-p)%d) continue;
x=((5*q+k-p)/d*x%l+l)%l;
if (ans<0) ans=x*n+p+1;
else ans=min(ans,x*n+p+1);
}
if (ans>=0) write(ans);
else printf("Orz mgh!!!");
putchar(10);
}
return 0;
}