• 51nod1079 poj2891 中国剩余定理与其扩展


    题目链接:http://www.51nod.com/Challenge/Problem.html#!#problemId=1079

    一个正整数K,给出K Mod 一些质数的结果,求符合条件的最小的K。例如,K % 2 = 1, K % 3 = 2, K % 5 = 3。符合条件的最小的K = 23。
     

    输入

    第1行:1个数N表示后面输入的质数及模的数量。(2 <= N <= 10)
    第2 - N + 1行,每行2个数P和M,中间用空格分隔,P是质数,M是K % P的结果。(2 <= P <= 100, 0 <= K < P)

    输出

    输出符合条件的最小的K。数据中所有K均小于10^9。

    输入样例

    3
    2 1
    3 2
    5 3

    输出样例

    23

    解题思路:中国剩余定理模板题
    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    ll gcd(ll a,ll b){return b?gcd(b,a%b):a;}
    ll n,a[100005],m[100005];
    //ax+by=gcd(a,b);
    //x=y1,y=x1-a/b*y1;
    void exgcd(ll a,ll b,ll &x,ll &y,ll &c)
    {
        if(!b){
            x=1; y=0; c=a;
            return;
        }
        exgcd(b,a%b,y,x,c);
        y-=a/b*x;
    }
    ll China()
    {
        ll x,y,c,lcm=1,ans=0;
        for(int i=1;i<=n;i++)
            lcm*=m[i];
        for(int i=1;i<=n;i++)
        {
            exgcd(lcm/m[i],m[i],x,y,c);
            x=(x%m[i]+m[i])%m[i];
            ans=(ans+x*lcm/m[i]*a[i])%lcm;
        }
        return (ans+lcm)%lcm;
    }
    int main()
    {
        while(cin>>n){
            for(int i=1;i<=n;i++)cin>>m[i]>>a[i];
            cout<<China()<<endl;
        }
        return 0;
    }

    题目链接:http://poj.org/problem?id=2891

    给定 2n2n 个正整数 a_1,a_2,cdots ,a_na1,a2,,an 和 m_1,m_2,cdots ,m_nm1,m2,,mn,求一个最小的正整数 xx,满足 forall iin[1,n],xequiv a_i (mod m_i )i[1,n],xai (modmi ),或者给出无解。

    输入格式

    多组数据。

    每组数据第一行一个整数 nn;
    接下来 nn 行,每行两个整数 m_i,a_imi,ai

    输出格式

    对于每组数据,若无解,输出 -11;否则输出一个非负整数,若有多解,输出最小的满足条件的答案。

    样例

    样例输入

    2
    8 7
    11 9

    样例输出

    31

    数据范围与提示

    对于全部数据,所有的输入都是非负的,并且可以用 6464 位有符号整数表示。保证 1le nle 10^5,m_igt a_i1n105,mi>ai

    解题思路:这种是一般情形,需要用扩展中国剩余定理。

    代码:

    #include<iostream>
    using namespace std;
    typedef long long ll;
    ll gcd(ll a,ll b){return b?gcd(b,a%b):a;}
    ll n,a[100005],m[100005];
    //ax+by=gcd(a,b);
    //x=y1,y=x1-a/b*y1;
    void exgcd(ll a,ll b,ll &x,ll &y,ll &c)
    {
        if(!b){
            x=1; y=0; c=a;
            return;
        }
        exgcd(b,a%b,y,x,c);
        y-=a/b*x;
    }
    ll inv(ll a,ll b)
    {
        ll x,y,c;
        exgcd(a,b,x,y,c);
        x=(x%(b/c)+(b/c))%(b/c);
        return x;
    }
    ll exCRT()
    {
        for(int i=2;i<=n;i++)
        {
            ll m1=m[i-1],m2=m[i],a1=a[i-1],a2=a[i],c=gcd(m1,m2);
            if((a2-a1)%c!=0)return -1;
            m[i]=m1*m2/c;
            a[i]=(inv(m1/c,m2/c)*(a2-a1)/c)%(m2/c)*m1+a1;
            a[i]=(a[i]%m[i]+m[i])%m[i];
        }
        return a[n];
    }
    int main()
    {
        while(cin>>n){
            for(int i=1;i<=n;i++)cin>>m[i]>>a[i];
            cout<<exCRT()<<endl;
        }
        return 0;
    }
  • 相关阅读:
    python初接触
    Visual Studio Code 必备插件
    C# 基础知识 -- 枚举(Enum)
    Visual Studio : Console.WriteLine(); 快捷键
    C# 调用Outlook发送邮件
    C# Dos、Unix、Mac文件格式之间的相互转换
    Treeview控件失去焦点,将选择的节点设置为高亮显示
    oracle中的Exists、In、Any、All
    TreeView控件如何控制滚动条的位置
    oracle 查看最大连接数与当前连接数
  • 原文地址:https://www.cnblogs.com/zjl192628928/p/10327555.html
Copyright © 2020-2023  润新知