同余模定理
定义:
• 所谓的同余,顾名思义,就是许多的数被一个数d去除,有相同的余数。d数学上的称谓为模。如a=6,b=1,d=5,则我们说a和b是模d同余的。因为他们都有相同的余数1。
• 数学上的记法为:
• a≡ b(mod d)
• 可以看出当n<d的时候,所有的n都对d同商,比如时钟上的小时数,都小于12,所以小时数都是模12的同余.对于同余有三种说法都是等价的,分别为:
• (1) a和b是模d同余的.
• (2) 存在某个整数n,使得a=b+nd .
• (3) d整除a-b.
• 可以通过换算得出上面三个说话都是正确而且是等价的.
定律:
• 同余公式也有许多我们常见的定律,比如相等律,结合律,交换律,传递律….如下面的表示:
• 1)a≡a(modd)
• 2)a≡b(modd)→b≡a(mod d)
• 3)(a≡b(modd),b≡c(mod d))→a≡c(mod d)
• 如果a≡x(modd),b≡m(mod d),则
• 4)a+b≡x+m (mod d)
• 5)a-b≡x-m(mod d)
• 6)a*b≡x*m(mod d )
•
应用:
• (a+b)%c=(a%c+b%c)%c;
• (a*b)%c=(a%c*b%c)%c;
• 对于大数的求余,联想到进制转换时的方法,得到
• 举例如下,设大数 m=1234,模n
• 就等于((((1*10)%n+2%n)%n*10%n+3%n)%n*10%n+4%n)%n
大数求余的简单模板:
• #include<stdio.h>//大数求余,其中n(除数)不是大数
char a[1000];
int main()
int i,j,k,m,n;
{
while(scanf("%s%d",a,&n)!=EOF)
{
m=0;
for(i=0;a[i]!='\0';i++)
m=((m*10)%n+(a[i]-'0')%n)%n;
printf("%d\n",m);
}
return 0;
}
poj2635
• 题目描述:
• 给定一个大数K,K是两个大素数的乘积的值。(4<= K <= 10^100 )
• 再给定一个int内的数L (2 <=L <= 10^6 )
• 问这两个大素数中最小的一个是否小于L,如果小于则输出这个素数。
解题思路:
• 1、 Char格式读入K。把K转成千进制Kt,同时变为int型。
• 把数字往大进制转换能够加快运算效率。若用十进制则耗费很多时间,会TLE。
• 千进制的性质与十进制相似。
• 2、 高精度求模。
• 主要利用Kt数组和同余模定理。
• 例如要验证123是否被3整除,只需求模123%3
• 但当123是一个大数时,就不能直接求,只能通过同余模定理对大数“分块”间接求模
• (a+b)%c=(a%c+b%c)%c;
• (a*b)%c=(a%c*b%c)%c;
• 具体做法是:
• 先求1%3 = 1
• 再求(1*10+2)%3 = 0
• 再求 (0*10+3)% 3 = 1
• 那么就间接得到123%3=0,这是显然正确的
• 而且不难发现, (1*10+2)*10+3 = 123
• 这是在10进制下的做法,千进制也同理,*10改为*1000就可以了