《算法竞赛进阶指南》Xiao 9*大战朱最学

Xiao 9*大战朱最学

http://www.nowcoder.com/questionTerminal/65e6bc3af3ae45b185a17002f3210a44

关键词:excrt

从题意我们可以简单地理解到这是中国剩余定理,那么我们就愉愉快快的把这个题交了上去

然后你AC了 想着双倍经验的你高高兴兴地拿去交 poj2891

发现只有40分

(黑人问号??)

那么我们一起再回去学一次CRT(中国剩余定理)

当m1,m2,m3,m4,m5,……mn 两两互质的时候

x≡ai(mod mi)

我们得到的答案将会是

x = Σ ai * Mi * ti (i<=n)
Mi = m / mi (m为所有m的积)
ti 为 Mi * ti ≡ 1 (mod mi)的一个解

但是我们再回到这个题目 不互质!!!

所以可以用

数学归纳法!

对他就叫excrt

假设 前k-1的方程的通解是 x+i*m (m为前面所有%数的lcm)

要满足第k个方程 x+i*m ≡ ak(mod mk)

移项 i*m ≡ ak-x(mod mk)

如果可以求出 i x’=x+i*m 就是解 然后接着推

所以就是答案了!!

CRT:

#include<iostream>
#include<stdio.h>
#include<cmath>
#include<algorithm>
#include<string.h>
#define LL long long
using namespace std;
LL a[12],b[12],n,M=1;
inline LL exgcd(LL a,LL b,LL &x,LL &y)
{
    if(!b){
        x=1,y=0;
        return a;
    }
    LL d=exgcd(b,a%b,x,y);
    LL z=x;x=y,y=z-(a/b)*y;
    return d;
}
inline LL crt()
{
    LL ans=0;
    for(LL i=1;i<=n;i++)
    {
        LL x,y;
        exgcd(M/a[i],a[i],x,y);
        x=(x%a[i]+a[i])%a[i];
        ans+=M/a[i]*x*b[i];
        ans%=M;
    }
    return ans;
}
int main()
{
    scanf("%d",&n);
    for(LL i=1;i<=n;i++) scanf("%lld%lld",&a[i],&b[i]),M*=a[i];
    printf("%lld",crt());
    return 0;
}

EX_CRT:

#include<iostream>
#include<stdio.h>
#include<string.h>
#include<cmath>
#include<algorithm>
#include<queue>
#include<stack>
#include<map>
#define LL long long
#define debug cout<<"bug"<<endl
using namespace std;
inline int exgcd(LL a,LL b,LL &x,LL &y)
{
    if(b==0){
        x=1,y=0;
        return a;
    }
    int d=exgcd(b,a%b,x,y);
    LL z=x;
    x=y,y=z-y*(a/b);
    return d;
}
int n,flag;
LL a1,m1,a,m,lcm,x,y,d,t,c;
int main()
{
    while(~scanf("%d",&n))
    {
        flag=0; 
        scanf("%lld%lld",&a1,&m1);
        n--;
        while(n--)
        {
            scanf("%lld%lld",&a,&m);
            if(flag) continue;
            c=m-m1;
            d=exgcd(a1,a,x,y);
            if(c%d) 
            {
                flag=1;
                continue;
            }
            x=x*c/d;
            a/=d;
            x=(x%a+a)%a;
            m1=m1+x*a1;
            a1*=a; 
        }
        if(flag) printf("-1\n");
        else printf("%lld\n",m1);
    }

    return 0;
}
全部评论

相关推荐

10-16 22:56
门头沟学院 C++
1234567800:歌尔今年给211开14-15k吗,我本地人连面试都不给😂
点赞 评论 收藏
分享
评论
点赞
收藏
分享
牛客网
牛客企业服务