poj2891(线性同余方程组)

一个exgcd解决一个线性同余问题,多个exgcd解决线性同余方程组。

Strange Way to Express Integers

Time Limit: 1000MS   Memory Limit: 131072K
Total Submissions: 12001   Accepted: 3797

Description

Elina is reading a book written by Rujia Liu, which introduces a strange way to express non-negative integers. The way is described as following:

Choose k different positive integers a1, a2, …, ak. For some non-negative m, divide it by every ai (1 ≤ ik) to find the remainder ri. If a1, a2, …, ak are properly chosen, m can be determined, then the pairs (ai, ri) can be used to express m.

“It is easy to calculate the pairs from m, ” said Elina. “But how can I find m from the pairs?”

Since Elina is new to programming, this problem is too difficult for her. Can you help her?

Input

The input contains multiple test cases. Each test cases consists of some lines.

  • Line 1: Contains the integer k.
  • Lines 2 ~ k + 1: Each contains a pair of integers ai, ri (1 ≤ ik).

Output

Output the non-negative integer m on a separate line for each test case. If there are multiple possible values, output the smallest one. If there are no possible values, output -1.

Sample Input

2
8 7
11 9

Sample Output

31

Hint

All integers in the input and the output are non-negative and can be represented by 64-bit integral types.

#include <iostream>
#include <stdio.h>
#include <string.h>
#include <algorithm>
#include <stdlib.h>
using namespace std;
#define N 10100

long long a[N],r[N];

long long cal_axb(long long a,long long b,long long mod)
{
    long long sum=0;
    while(b)
    {
        if(b&1) sum=(sum+a)%mod;
        b>>=1;
        a=(a+a)%mod;
    }
    return sum;
}

// ax+by = gcd(a,b) ->求解x,y 其中a,b不全为0,可以为负数
// 复杂度:O(log2a)
void extendgcd(long long a,long long b,long long &x,long long &y)
{
    if(a%b==0)
    {
        //到了终止条件
        x=0; y=1;
        return ;
    }
    extendgcd(b,a%b,x,y);
    long long tmpx;
    tmpx=y;
    y=x - (a/b)*y;
    x=tmpx;
}

long long Multi_ModX(long long m[],long long r[],int n)
{
    long long m0,r0;
    m0=m[0]; r0=r[0];
    for(int i=1;i<n;i++)
    {
        long long m1=m[i],r1=r[i];
        long long tmpd=__gcd(m0,m1);
        if( (r1 - r0)%tmpd!=0 ) return -1;
        long long k0,k1;
        extendgcd(m0,m1,k0,k1);
        k0 *= (r1-r0)/tmpd;
        //k0会不会很大
        m1 *= m0/tmpd;
        r0 = (cal_axb(k0,m0,m1)+r0)%m1;
        m0=m1;
    }
    return (r0%m0+m0)%m0;
}

int main()
{
    int k;
    while(cin>>k)
    {
        for(int i=0;i<k;i++)
            cin>>a[i]>>r[i];
        cout<<Multi_ModX(a,r,k)<<endl;
    }
    return 0;
}
时间: 2025-01-01 21:00:00

poj2891(线性同余方程组)的相关文章

求解一元线性同余方程组模版

解法:直接上模版. 扩展欧几里德的模版: typedef long long LL; LL ex_gcd(LL a,LL b,LL &x,LL &y) { if(b==0) { x=1; y=0; return a; } LL d=ex_gcd(b,a%b,x,y); LL t=x; x=y; y=t-a/b*y; return d; } 求解一元线性同余方程组模版: LL solve(LL n) { LL a1,r1,a2,r2; LL a,b,c,r,x,y; bool ifhave=

HDU1573:X问题(解一元线性同余方程组)

题目:http://acm.hdu.edu.cn/showproblem.php?pid=1573 题目解析;HDU就是坑,就是因为n,m定义成了__int64就WAY,改成int就A了,无语. 这题就是求解一元线性同余方程组的解满组小于正整数n的数目.最小正整数的解为X=(X*(c/d)%t+t)%t;  X=a1*X+r1;其中X为扩展欧几里得解出来的特解,这m个方程组的循环区间为lcm(a1,a2,a3...am),所以答案为(n-X)/lcm+1; #include <iostream>

HDU1573 X问题【一元线性同余方程组】

题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=1573 题目大意: 求在小于等于N的正整数中有多少个X满足:X mod a[0] = b[0], X mod a[1] = b[1], X mod a[2] = b[2], -, X mod a[i] = b[i], - (0 < a[i] <= 10). 思路: 先求出数组b[]中所有数的最小公倍数lcm,再求解出该一元线性同余方程组在lcm范围内的解为a,题目要 求解x是小于等于N的正整数,则

HDU3579:Hello Kiki(解一元线性同余方程组)

题目:http://acm.hdu.edu.cn/showproblem.php?pid=3579 题目解析:求一元线性同余方程组的最小解X,需要注意的是如果X等于0,需要加上方程组通解的整数区间lcm(a1,a2,a3,...an). 别的就没什么注意的了. #include <iostream> #include <stdio.h> #include <string.h> #include <algorithm> #include <math.h&

poj3708(公式化简+大数进制装换+线性同余方程组)

刚看到这个题目,有点被吓到,毕竟自己这么弱. 分析了很久,然后发现m,k都可以唯一的用d进制表示.也就是用一个ai,和很多个bi唯一构成. 这点就是解题的关键了. 之后可以发现每次调用函数f(x),相当于a(ai),b(bi)了一下.这样根据置换的一定知识,一定会出现循环,而把循环的大小看成取模,把从m->k的看成余,于是可以建立一个线性同余方程. 直接用模板解决之.. Recurrent Function Time Limit: 1000MS   Memory Limit: 65536K To

POJ2891 Strange Way to Express Integers【一元线性同余方程组】

题目链接: http://poj.org/problem?id=2891 题目大意: 选择k个不同的正整数a1.a2.-.ak,对于某个整数m分别对ai求余对应整数ri,如果 适当选择a1.a2.-.ak,那么整数m可由整数对组合(ai,ri)唯一确定. 若已知a1.a2.-.ak以及m,很容易确定所有的整数对(ai,ri),但是题目是已知a1. a2.-.ak以及所有的整数对(ai,ri),求出对应的非负整数m的值. 思路: 题目可以转换为给定一系列的一元线性方程 x ≡ r1( mod a1

HDU3579 Hello Kiki【一元线性同余方程组】

题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=3579 题目大意: Kiki有X个硬币,她用不同的方式数了N次,每次她把硬币分成大小相等的组,记录每次一组硬币 的个数Mi和数完最后剩余的硬币数Ai.那么问题来了:总共有多少枚硬币? 思路: 典型的一元线性同余方程组X = Ai(mod Mi)求解.题目要求输出最小正整数解,则如果求得同余 方程组的解为0,那么答案就是所有Mi的最小公倍数. AC代码: #include<iostream> #in

HDU 1573 X问题(一元线性同余方程组)

X问题 Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 3850    Accepted Submission(s): 1228 Problem Description 求在小于等于N的正整数中有多少个X满足:X mod a[0] = b[0], X mod a[1] = b[1], X mod a[2] = b[2], -, X mo

POJ 2891 Strange Way to Express Integers(一元线性同余方程组模版题)

题意:给出n个模方程组:x mod ai = ri.求x的最小正值.如果不存在这样的x,那么输出-1. 涉及的数论知识: 对于一般式ax ≡ b(mod m) 当a=1时,两个同余方程就可以合并成一个同余方程 比如对于本题: x mod a1=r1 x mod a2=r2 有不定方程: x=r2+a2*y2 x=r2+a2*y2 联立: a1y1+a2*(-y2)=r2-r1 可以通过扩展gcd求解出y1,回带解得特解(x*) 所以通解是满足合并后的同余方程的所有同余类解:x mod (lcm(