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;
}
快速幂模的应用: