《数论及应用》第3章 同余问题

1.同余概述


基本定理:若 a*c≡b*c(mod m) 且(c,m)=d , 则 a≡b(mod m/d)

同余定理的应用: poj 2769 

http://poj.org/problem?id=2769

#include <stdio.h>
#include <string.h>
#define N 1000001
int a[N];
bool flag[N];
int main()
{
    int T;
    scanf("%d",&T);
    while(T--)
    {
        int n,i;
        scanf("%d",&n);
        for(i=1;i<=n;i++)
        scanf("%d",&a[i]);
        int tag;
        for(i=1;;i++)
        {
            memset(flag,0,sizeof(bool)*i);
            tag=1;
            for(int j=1;j<=n;j++)
            {
                if(flag[a[j]%i])
                {
                    tag=0;
                    break;
                }
                flag[a[j]%i]=1;
            }
            if(tag)
            break;
        }
        printf("%d\n",i);
    }
    return 0;
}

http://acm.hdu.edu.cn/showproblem.php?pid=1021

两种方法:

#include <stdio.h>
#define N 1000001
int a[N];
int main()
{
    a[0]=7%3;
    a[1]=11%3;
    for(int i=2;i<=N;i++)
    a[i]=(a[i-1]%3+a[i-2]%3)%3;
    int n;
    while(scanf("%d",&n)!=EOF)
    {
        if(a[n])
        printf("no\n");
        else
        printf("yes\n");
    }
    return 0;
}

#include <stdio.h>
int main()
{
    int n;
    while(scanf("%d",&n)!=EOF)
    {
        if(n%4==2)
        printf("yes\n");
        else
        printf("no\n");
    }
    return 0;
}

http://acm.hdu.edu.cn/showproblem.php?pid=2035

#include <stdio.h>
int main()
{
    int m,n;
    while(scanf("%d%d",&m,&n),m||n)
    {
        int ans=1;
        for(int i=1;i<=n;i++)
        ans=(ans*m)%1000;
        printf("%d\n",ans);
    }
    return 0;
}


2.线性同余方程


 形如 ax ≡ b ( mod m ) 且 x 是未知整数的同余式叫一元线性同余方程

扩展欧几里得:

void exgcd(long long a,long long b,long long &d,long long &x,long long &y)
{
    if(b==0)
    {
        x=1;y=0;
        d=a;
        break;
    }
    else
    {
        exgcd(b,a%b,d,x,y);
        long long temp=x;
        x=y;
        y=temp-(a/b)*y;
    }
}
求方程所有解:

int f(int a,int b,int m)
{
    exgcd(a,m,d,x,y);
    if(b%d)
    return -1;
    x=x*(b/d)%m;
    for(i=1;i<=d;i++)
    ans[i]=(x+(i-1)*m/d)%m;
}


解一元线性同余方程组:

书上的一个代码:

int solve()
{
    scanf("%I64d%I64d",&a1,&r1);
    for(i=1;i<n;i++)
    {
        scanf("%I64d%I64d",&a2,&r2);
        a=a1;b=a2;c=r2-r1;
        exgcd(a,b,d,x0,y0);
        if(c%d)
        {
            ifhave=0;
        }
        int t=b/d;
        x0=(x0*(c/d)%t+t)%t;
        r1=a1*x0+r1;
        a1=a1*(a2/d);
    }
    if(!ifhave)
    {
        r1=-1;
    }
    return r1;
}

自己给自己找了个例子算了一下是对的呢

x  2 mod 6 ;

x  3 mod 17 ;

解出 x = 20 ;

#include <stdio.h>
const int n=2;
long long d;
long long x0,y0;
void exgcd(long long a,long long b,long long &d,long long &x,long long &y)
{
    if(b==0)
    {
        x=1;y=0;
        d=a;
        return;
    }
    else
    {
        exgcd(b,a%b,d,x,y);
        long long temp=x;
        x=y;
        y=temp-(a/b)*y;
    }
}
int main()
{
    long long a1,a2,r1,r2;
    long long a,b,c;
    int ifhave=1;
    scanf("%I64d%I64d",&a1,&r1);
    for(int i=1;i<n;i++)
    {
        scanf("%I64d%I64d",&a2,&r2);
        a=a1;b=a2;c=r2-r1;
        exgcd(a,b,d,x0,y0);
        if(c%d)
        {
            ifhave=0;
        }
        int t=b/d;
        x0=(x0*(c/d)%t+t)%t;
        r1=a1*x0+r1;
        a1=a1*(a2/d);
    }
    if(!ifhave)
    {
        r1=-1;
    }
    printf("%I64d\n",r1);
    return 0;
}

多元线性同余方程:

方程 a1x1+a2x2+a3x3+……+anxn+b 0 (mod m)有解的充要条件是(a1,a2,a3,……,an,m)| b

若方程有解,则解的个数是 (m^(n-1))*(a1,a2,a3,……,an,m)

思路:令 d=(a1,a2,a3,……,an,m)  d1=(a1,a2,a3,……,a(n-1),m)  (d1,an)=d 即 an*xn+b 0(mod m)

方程分成了两部分:

a1x1+a2x2+a3x3+……+a(n-1)x(n-1)+b1d1  0 (mod m)   b1d1=an*xn+b ;

an*xn+b  0(mod m)  ;

http://poj.org/problem?id=2891

#include <stdio.h>
int n;
long long d;
long long x0,y0;
void exgcd(long long a,long long b,long long &d,long long &x,long long &y)
{
    if(b==0)
    {
        x=1;y=0;
        d=a;
        return;
    }
    else
    {
        exgcd(b,a%b,d,x,y);
        long long temp=x;
        x=y;
        y=temp-(a/b)*y;
    }
}
int main()
{
    long long a1,a2,r1,r2;
    long long a,b,c;
    while(scanf("%d",&n)!=EOF){
    int ifhave=1;
    scanf("%I64d%I64d",&a1,&r1);
    for(int i=1;i<n;i++)
    {
        scanf("%I64d%I64d",&a2,&r2);
        a=a1;b=a2;c=r2-r1;
        exgcd(a,b,d,x0,y0);
        if(c%d)
        {
            ifhave=0;
        }
        int t=b/d;
        x0=(x0*(c/d)%t+t)%t;
        r1=a1*x0+r1;
        a1=a1*(a2/d);
    }
    if(!ifhave)
    {
        printf("-1\n");
        continue;
    }
    printf("%I64d\n",r1);}
    return 0;
}



3.高次同余方程

这几天要开学了,线性同余方程和高次同余方程看得有些迷糊,暂时就放一放,看看后面的……



4.快速幂模m算法 

整数快速幂:


一般方法:

int mod(int a,int b,int m)
{
    int ans=1;
    for(int i=1;i<=m;i++)
    {
        ans=ans*b%m;
    }
    return ans;
}

二分思想的快速幂:

long long qkmod(long long a,long long b,long long m)
{
    long long ans=1;
    while(b)
    {
        if(b&1)
        {
            ans=ans*b%m;
            b--;
        }
        b/=2;
        a=a*a%m;
    }
    return ans;
}

矩阵快速幂:

typedef struct 
{
    int m[maxn][maxn];
}Matrax;
Matrax a,per;
int n,M;
void init()
{
    for(int i=0;i<n;i++)
    for(int j=0;j<n;j++)
    {
        scanf("%d",&a.m[i][j]);
        a.m[i][j]%=M;
        per.m[i][j]=(i==j);// 单位矩阵
    }
}
Martrax multi(Matrax a,Matrax b)
{
    Matrax c;
    for(int i=0;i<n;i++)
    for(int j=0;j<n;j++)
    {
        c.m[i][j]=0;
        for(int k=0;k<n;k++)
        {
            c.m[i][j]+=a.m[i][k]*b.m[k][j];
        }
        c.m[i][j]%=M;
    }
    return c;
}
Matrax power(int k)
{
    Matrax c,p,ans=per;
    p=a;
    while(k)
    {
        if(k&1)
        {
            ans=multi(ans,p);
            k--;
        }
        k/=2;
        p=multi(p,p);
    }
    return ans;
}

快速幂模的应用:


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值