1. 程式人生 > >【EXCRT模板】POJ2891/LuoGu4777Strange Way to Express Integers拓展中國剩餘定理

【EXCRT模板】POJ2891/LuoGu4777Strange Way to Express Integers拓展中國剩餘定理

這道題需要exgcd的基礎

POJ的題幹描述十分噁心

Strange Way to Express Integers
Time Limit: 1000MS        Memory Limit: 131072K
Total Submissions: 21217        Accepted: 7120
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 ≤ i ≤ k) 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
≤ i ≤ k). 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. Source POJ Monthly--2006.07.30, Static
POJ2891

還是洛谷的好,題意就是同模方程組(模數不互質)

洛谷POJ區別就是POJ有判斷誤解和多組資料(POJ傳統,好多多組資料)

這種最重要的就是推導過程了

網上還是很多的,我就再贅述一遍

x = r1(% a1)

x = r2(%a2)

即x = k1*a1*+r1 = k2*a2+r2

移項k1*a1 = k2*a2+r2-r1(%a2)

同模a2,即k1*a1 = r2-r1(%a2)

這裡用exgcd,求出k1通解即k1 = k0+a2/gcd(a,b)*t

帶入,也就是x = a1*k1+r1 = a1*(k0+a2/gcd(a,b)*t)+r1 = a1*k0+lcm(a,b)+r1

同模一個lcm(a1,a2)即a1*k0+r1 = x(%lcm(a1,a2))

這樣我們就每次用一個exgcd可以把方程合併了(複雜度應該是nlogn)

同模方程組無解就是exgcd無解,判斷下就好了

注意:

1.發現無解之後不可以break,因為資料還沒有讀完就進行下一組,肯定是錯的

2.POJ此題沒有資料範圍,也就是說本題最好不要離線,只要先讀入一個數,然後線上搞即可(時間相差不大,只是快了一點但是省記憶體,原來蒟蒻的我2.27MB,現在還是蒟蒻的我線上搞0.86MB)

好了上程式碼

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 using namespace std;
 5 typedef long long ll;
 6 ll n,a,r,x,y;bool flag=0;
 7 inline ll gcd(ll a,ll b){return b?gcd(b,a%b):a;}
 8 inline ll lcm(ll a,ll b){return a/gcd(a,b)*b;}
 9 ll ksc(ll a,ll b,ll mod)
10 {
11     ll fina=0;int kk=1;
12     if(a<0)a=-a,kk=-kk;
13     if(b<0)b=-b,kk=-kk;
14     while(b)
15     {
16         if(b%2)fina=(fina+a)%mod;
17         a=(a+a)%mod,b=b/2;
18     }
19     return fina%mod*kk;
20 } 
21 void exgcd(ll a,ll b)
22 {
23     if(!b)
24         x=1,y=0;
25     else
26     {
27         exgcd(b,a%b);
28         ll tt=x;
29         x=y,y=tt-a/b*x;
30     }
31 }
32 int main()
33 {
34     while(scanf("%lld",&n)==1 && n)
35     {
36         flag=0;
37         scanf("%lld%lld",&a,&r);
38         for(register ll i=1,a1,r1,gc,aa,bb,cc;i<n;i++)
39         {
40             a1=a,r1=r;
41             scanf("%lld%lld",&a,&r);
42             aa=a1,bb=a,cc=r-r1,gc=gcd(aa,bb);
43             if(cc%gc){flag=1;continue;}
44             aa/=gc,bb/=gc,cc/=gc;
45             exgcd(aa,bb);
46             r=(ksc(x,cc,bb)+bb)%bb*a1+r1;
47             a=lcm(a1,a);
48         }
49         if(flag){puts("-1");continue;}
50         ll aa=1,bb=a,cc=r;
51         exgcd(aa,bb);
52         printf("%lld\n",(ksc(x,cc,bb)+bb)%bb);
53     }
54     return 0;
55 }