猜数字[中国剩余定理]

求解中国剩余定理问题
探讨一组特定条件下求解最小非负整数n的方法,该整数满足特定的除法条件。输入包括两组数字,需利用中国剩余定理或类似算法找到满足条件的整数n。

现有两组数字,每组k个,第一组中的数字分别为:a1,a2,...,ak表示,第二组中的数字分别用b1,b2,...,bk表示。其中第二组中的数字是两两互素的。求最小的非负整数n,满足对于任意的i,n - ai能被bi整除。

输入格式

输入数据的第一行是一个整数k,(1 ≤ k ≤ 10)。接下来有两行,第一行是:a1,a2,...,ak,第二行是b1,b2,...,bk

输出格式

输出所求的整数n。

输入样例

3
1 2 3
2 3 5

输出样例

23

数据规模与约定

所有数据中,第一组数字的绝对值不超过109(可能为负数),第二组数字均为不超过6000的正整数,且第二组里所有数的乘积不超过1018
每个测试点时限1秒

注意:对于C/C++语言,对64位整型数应声明为long long,如使用scanf, printf函数(以及fscanf, fprintf等),应采用%lld标识符。

题目来源天津市NOI选拔赛2009年第三轮
=============================================================================
这题本应该是中国剩余定理,但是最后一个点怎么都WA,可能是溢出了吧,改成递增的就A了。

program number;

var
  m, a: array[1..100] of longint;
  k:    longint;

{
  procedure Scan;
  var
    i: longint;
  begin
    readln(k);
    for i := 1 to k do
      Read(a[i]);
    readln;
    for i := 1 to k do
      Read(m[i]);
    readln;
  end;

  function Gcd_Ext(a, b: int64; var p, q: int64): int64;
  var
    t: int64;
  begin
    if b = 0 then
    begin
      Gcd_Ext := a;
      p := 1;
      q := 0;
    end
    else
    begin
      Gcd_Ext := Gcd_Ext(b, a mod b, p, q);
      t := p;
      p := q;
      q := t - q * (a div b);

    end;
  end;

  function Crt: int64;
  var
    MM, Mi, p, q: int64;
    i: longint;
  begin
    MM := 1;
    for i := 1 to k do
      MM := MM * m[i];

    Crt := 0;
    for i := 1 to k do
    begin
      Mi := MM div m[i];
      Gcd_Ext(Mi, m[i], p, q);
      Crt := (Crt + Mi * p * a[i]) mod MM;
    end;
    if Crt < 0 then
      Inc(Crt, MM);
  end;

  procedure Main;
  begin
    Scan;
    Write(Crt);
  end;

begin
  Assign(input, 'number.in');
  reset(input);
  Assign(output, 'number.out');
  rewrite(output);

  Main;

  Close(input);
  Close(output);
end.
}
  procedure Scan;
  var
    i: longint;
  begin
    readln(k);
    for i := 1 to k do
      Read(a[i]);
    readln;
    for i := 1 to k do
      Read(m[i]);
    readln;
    for i := 1 to k do
      a[i] := ((a[i] mod m[i]) + m[i]) mod m[i];
  end;

  function Crt: int64;
  var
    i:    longint;
    delt: int64;
  begin
    delt := 1;
    Crt  := 0;
    for i := 1 to k do
    begin
      while Crt mod m[i] <> a[i] do
        Inc(Crt, delt);
      delt := delt * m[i];
    end;
  end;

  procedure Main;
  begin
    Scan;
    Write(Crt);
  end;

begin
  Assign(input, 'number.in');
  reset(input);
  Assign(output, 'number.out');
  rewrite(output);
  Main;
  Close(input);
  Close(output);
end.


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值