POJ 2891 Strange Way to Express Integers

    技术2022-05-19  24

    告诉你k对a,b,x=ai mod bi,求满足条件最小的非负x,如果无解,输出-1

     

    参考:http://scturtle.is-programmer.com/posts/19363.html

    http://hi.baidu.com/edwardmj/blog/item/a1cd568087ad4cb26d81197c.html

     

     

    由于bi,bj不保证互素,不能用直接套中国剩余定理,做法是利用欧几里德扩展定理,将两个等式合并,然后再与其他的等式一一合并

     

    对于x=a1 mod b1,x= a2 mod b2,设x=a1+m*b1

    所以b1*m=a2-a1 mod b2,利用欧几里德扩展定理求出最小的非负m,那么x=a1+m*b1就已知,且x最小,如果无解,整个同余式组无解

     

    同时,x+k*b1是所有满足x=a1 mod b1的解,而x+k'*b2又是所有满足x=a2 mod b2的解

    那么,将x+k*b1与x+k'*b2合并,得到的式子就是x+k*lcm(b1,b2)

    于是,上面两个式子可以用x'=x mod lcm(b1,b2)来替代

    最后,就只剩下一个式子了,求得的最小的x就是答案

     

    对于一次同余式ax=b mod n,设d=gcd(a,n),则同余式有解的充要条件为d|b

    假设d=a*x'+n*y',则x0=b/d*x'一定为方程组的一个解,且共有d个解,(证明可以参考算法导论)最小正整数解为(x0%n/d+n/d)%(n/d)

     

    代码:

    #include<iostream> #include<cstdio> #include<memory.h> using namespace std; __int64 k,m,t; __int64 gcd(__int64 a,__int64 b) { if(b==0) return a; else return (b,a%b); } __int64 extend_euclid(__int64 a,__int64 b,__int64 &x,__int64 &y) { if(b==0) { x=1; y=0; return a; } __int64 d=extend_euclid(b,a%b,x,y); t=x; x=y; y=t-a/b*y; return d; } int main() { int i,flag; __int64 p,q,d,a1,a2,b1,b2,x,c; while(scanf("%I64d",&k)!=EOF) { scanf("%I64d%I64d",&b1,&a1); flag=0; for(i=0;i<k-1;i++) { scanf("%I64d%I64d",&b2,&a2); if(flag) continue; d=extend_euclid(b1,b2,p,q); c=a2-a1; if(c%d) { flag=1; continue; } t=b2/d; x=(c/d*p

    转载请注明原文地址: https://ibbs.8miu.com/read-2215862.html

    最新回复(0)