这道题曾经使用模拟跑步者的方法去求解,不过那样解法是一般的解法了。
这里使用数学的方式:孙子剩余定律(当然,叫中国剩余定律),因为是孙子提出的,因此外国也认得孙子是个数学家。
建议大家参考数论的专业书学习这个定律;
这里严格按照数论的方法写出全过程的程序,不像某些博客只给出最终步骤。方便大家结合程序和专业书本学习这个定律。
int g, s, t;
const int m1 = 23;
const int m2 = 28;
const int m3 = 33;
void extGCD(int a, int b)
{
if (b == 0)
{
s = 1, t = 0, g = a;
}
else
{
extGCD(b, a % b);
int tmp = s;
s = t;
t = tmp - a / b * t;
}
}
int a, b, c, m;
void preCalculateABCM()
{
m = m1 * m2 * m3; //本题==21252
int M1 = m / m1;
int M2 = m / m2;//=759
int M3 = m / m3;
extGCD(M1, m1);
int y1 = s;
if (y1 < 0)
{
int y = -y1;
y %= m1;
y1 = m1 - y;
}
extGCD(M2, m2);
int y2 = s;
if (y2 < 0)
{
int y = -y2;
y %= m2;
y2 = m2 - y;
}
extGCD(M3, m3);
int y3 = s;
if (y3 < 0)
{
int y = -y3;
y %= m3;
y3 = m3 - y;
}
a = M1 * y1;
b = M2 * y2;
c = M3 * y3;
}
int meetDates(int p, int e, int i, int d)
{
//p %= m1, e %= m2, i %= m3;
int x = p * a + e * b + i * c;
x %= m;
if(x <= d) x = m - (d - x);
else x = x - d;
return x;
}
int main()
{
preCalculateABCM();
int p,e,i,d, n = 0;
while (cin>>p>>e>>i>>d && -1 != d)
{
n++;
printf("Case %d: the next triple peak occurs in %d days.\n",
n, meetDates(p, e, i, d));
}
return 0;
}