您的位置:首页 > 产品设计 > UI/UE

2016 UESTC Training for Math Problem C-咸鱼的跑步比赛(解同余线性方程组)

2016-06-09 03:23 453 查看
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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  数学