zoukankan      html  css  js  c++  java
  • POJ 1006 Biorhythms (中国剩余定理)

    在POJ上有译文(原文右上角),选择语言:简体中文


    求解同余方程组:
    x=ai(mod mi) i=1~r, m1,m2,...,mr互质
    利用中国剩余定理
    令M=m1*m2*...*mr,Mi=M/mi
    因为mi两两互质,所以(Mi,mi)=1
    令Mi*yi=1(mod mi)的解为yi,即Mi模mi的逆元
    则方程的解为:
    (a1*M1*y1+a2*M2*y2+...+ar*Mr*yr)%M

    方法一:用扩展欧几里德求逆元

    #include <iostream>
    #include <stdio.h>
    #include <string.h>
    
    using namespace std;
    const int M=21252;
    int a[3],m[3]={23,28,33};
    int sp,se,si,d;
    int exgcd(int a,int b,int &x,int &y){
        if(b==0){
            x=1;
            y=0;
            return a;
        }
        int d=exgcd(b,a%b,x,y);
        int tmp=x;
        x=y;
        y=tmp-a/b*y;
        return d;
    }
    int main()
    {
        int cases=0,ans;
        int ni[3],Mi[3],x,y;
        //因为mi是固定的,所以可以先将对应的逆元用扩展欧几里德求出来
        for(int i=0;i<3;i++){
            Mi[i]=M/m[i];
            exgcd(Mi[i],m[i],x,y);
            ni[i]=x;
        }
        while(scanf("%d%d%d%d",&sp,&se,&si,&d)!=EOF){
            if(sp==-1)
                break;
            a[0]=sp;a[1]=se;a[2]=si;
            ans=0;
            for(int i=0;i<3;i++){
                ans=(ans+(a[i]*Mi[i]%M)*ni[i]%M)%M;
                ans=(ans+M)%M;
            }
            if(ans<=d){
                ans=ans+M-d;
            }
            else
                ans=ans-d;
            printf("Case %d: the next triple peak occurs in %d days.
    ",++cases,ans);
    
        }
        return 0;
    }
    View Code

    方法二:枚举求Mi*yi

    #include <iostream>
    #include <stdio.h>
    #include <string.h>
    #include <algorithm>
    
    using namespace std;
    
    const int M=21252;
    int m[3]= {23,28,33};
    int a[3];
    int sp,se,si,d;
    int Mii[3],Mi[3];
    int value;
    
    //求最大公约数,最小公倍数则两数相乘除以它们的最大公约数
    int gcd(int a,int b) {
        if(b==0)
            return a;
        else
            return gcd(b,a%b);
    }
    int main() {
        int cases=0;
        Mii[0]=Mi[0]=m[1]*m[2];
        Mii[1]=Mi[1]=m[0]*m[2];
        Mii[2]=Mi[2]=m[0]*m[1];
        //枚举求Mi*yi
        for(; Mii[0]%m[0]!=1; Mii[0]+=Mi[0]) {
        }
        for(; Mii[1]%m[1]!=1; Mii[1]+=Mi[1]) {
        }
        for(; Mii[2]%m[2]!=1; Mii[2]+=Mi[2]) {
        }
        while(scanf("%d%d%d%d",&sp,&se,&si,&d)!=EOF) {
            if(sp==-1)
                break;
            a[0]=sp;
            a[1]=se;
            a[2]=si;
            value=((Mii[0]*a[0]+Mii[1]*a[1]+Mii[2]*a[2])%M+M)%M;
            int ans;
            if(value<=d) {
                ans=value+M-d;
            } else
                ans=value-d;
            printf("Case %d: the next triple peak occurs in %d days.
    ",++cases,ans);
    
    
        }
        return 0;
    }
    View Code
  • 相关阅读:
    cJSON库源码分析
    cJSON 使用详解
    day23
    day22
    作业21
    day21
    作业20
    day20
    作业
    day19
  • 原文地址:https://www.cnblogs.com/chenxiwenruo/p/3556308.html
Copyright © 2011-2022 走看看