C - 咸鱼的跑步比赛
Time Limit: 3000/1000MS (Java/Others) Memory Limit: 65535/65535KB (Java/Others)
旅行到喵哈村的谭爷,发现一个超自然现象!
这里的咸鱼是跳着移动的!而且每次移动的距离相同,而且都是整数!!
突然,他有了强烈的好奇心,想知道咸鱼们能不能汇合到一起嘞? 为了简化了问题,他强行将咸鱼们放在一条直(数)线(轴)上,并且将所在的位置强行规定成了在正半轴的整点!
先在给你此刻咸鱼的只数,其跳跃的距离ni,第i只咸鱼的位置ai,有没有合适的位置x让咸鱼们集合在一起。
(咸鱼可以向左也可以向右跳哟~)
如果没有输出-1
有的话找到并输出一个最小的符合条件的正整数x
谭爷仔细想了想,感觉暴力似乎是没法做的!
Input
第一行,咸鱼只数n
n<=100
第二到第n+1行有两个正整数表示ni 和 ai
1<=ni,ai<=1000
Output
一行,表示最小的符合条件的正整数x 可能很大!请用long long
解题思路:
设咸鱼汇合的位置是x,则|x-ai|mod ni=0;即x与ai modni同余,所以我们可以考虑解同余线性方程组,得出最小正整数解;
(1)只有一个方程时,答案为ai%ni;
(2)只有两个方程时,
x=k1*n1+a1;
x=k2*n2+a2;
联立:
K1*n1-k2*n2=a1-a2;
根据贝祖定理,有解当且仅当(a1-a2)|gcd(k1,k2);
考虑扩展欧几里得:
两边同时乘以gcd(n1,n2)/(a1-a2);
得到:
K1*x-k2*y=gcd(k1,k2);
解x
X*=(a1-a2)/gcd(n1,n2);
X=x*n1+a1;
(3)有多个方程:
X作为新合并的方程的a,lcm(n1,n2)作为新的方程的n;如此两两合并;
代码:
#include<stdio.h>
typedef long long LL;
LL r[105], a[105];
LL ExGcd(LL a,LL b,LL &x,LL &y)
{
if(b==0) {x=1;y=0;return a;}
LL r=ExGcd(b,a%b,y,x);
y-=x*(a/b);
return r;
}
LL Modline(LL r[],LL a[],int n)
{
LL rr=r[0],aa=a[0];
for(int i=1;i<n;i++)
{
LL C=r[i]-rr,x,y;
LL d=ExGcd(aa,a[i],x,y);
if((C%d)!=0) return -1;
LL Mod=a[i]/d;
x=((x*(C/d)%Mod)+Mod)%Mod;
rr=rr+aa*x;
aa=aa*a[i]/d;
}
return rr;
}
int main()
{
int t;
scanf("%d",&t);
if(t==1)
{
scanf("%lld%lld",&a[0],&r[0]);
printf("%lld",r[0]%a[0]);
return 0;
}
for(int i=0;i<t;i++)
scanf("%lld%lld",&a[i],&r[i]);
LL ans=Modline(r,a,t);
printf("%lld",ans);
return 0;
}