|||
有一次我问老爸:2的100次方的结果,其个位数是几?当时我也不知道是几,但想想应该有些规律,研究了一下,发现应该是六,这个不是硬乘出来的,而且推断的结果.我用手机上的Python环境计算了一下2**100,结果一长串,个位的确是六。于是,我再进一步思考,是否可以求解任意一个自然数的任意自然数次方的结果,其个位数是否可以心算出来?经过努力,发现都是有规律的。
最近在学习VC++,于是想把这点思考的结果固化下来,代码如下,在DOS下运行。写了两个函数,第一个函数让我理清了思路,第二个函数非常简洁但不容易理解,实质上就是对第一个函数的浓缩。
-----------C++源代码--开始-------------------------------
# include <iostream.h>
/*求取结果的原理:个位数的幂决定了结果的幂。对某个数而言,特定倍数的结果总是一样的尾数,如3的4n次幂总是1结尾,因此可以容易算出4n+1次方的尾数为1*3,4n+2次方的尾数 1*3*3=9,4n+3 次方的尾数为 1*3*3*3=27,即为7.因此可以知道任意次方的结果的尾数。
因此,对底数以10取模,对幂则根据不同的数字来决定。
di: 底数 mi幂
digewei:底的个位数,它决定了结果的个位数
miyu:幂的余数,取模之后。
逐步分析即可以得到结果,如方法1所示。也可以将结果总结成一个数组,即方法2所使用的结果。
*/
int GetLastDigit_1(int di, int mi)
{
int digewei;
int miyu;
digewei=di % 10;
switch (digewei)
{
case 0: return 0; break;
case 1: return 1; break;
case 5: return 5; break;
case 6: return 6; break;
case 2:
miyu=mi%4;
switch (miyu)
{
case 0: return 6;break; // 2^4n=6
case 1: return 2;break; //2^4n+1=6*2=12, so 2
case 2: return 4;break; //2^4n+2=6*2*2=24, so 4
case 3: return 8;break; //2^4n+3=6*2*2*2=48, so 8;
};
break;
case 3:
miyu=mi%4;
switch (miyu)
{
case 0: return 1;break; //3^4n=1
case 1: return 3;break; //3^4n+1=1*3=3, so 3
case 2: return 9;break; //3^4n+2=1*3*3=9, so 9
case 3: return 7;break; //3^4n+3=1*3*3*3=27, so 27
};
break;
case 4:
miyu=mi%2;
switch(miyu)
{
case 0: return 6;break; //4^2n=6
case 1: return 4;break; //4^2n+1=6*4=4;
};
break;
case 7:
miyu=mi%4;
switch (miyu)
{
case 0: return 1;break; //7^4n=49*49=1
case 1: return 7;break; //7^4n+1=1*7=7;
case 2: return 9;break; //7^4n+2=1*7*7=49, so 9
case 3: return 3;break; //7^4n+3=1*7*7*7=49*7=3
};
break;
case 8:
miyu=mi%4;
switch (miyu)
{
case 0: return 6;break; //8^4n=64*64=16;
case 1: return 8;break; //8^4n+1=6*8=48, so 8
case 2: return 4;break; //8^4n+2=6*8*8, so 4
case 3: return 2;break; //8^4n+3=6*8*8*8, so 2
}
break;
case 9:
miyu=mi%2;
switch (miyu)
{
case 0: return 1;break; //9^2n=81^n, so 1
case 1: return 9;break; //9^2n+1=1*9=9;
};
break;
};
};
int GetLastDigit_2(int di, int mi)
{/*根据方法1的结果,将其整理成数组来直接处理更为节省代码。
数据的第一维对应底的个位数,从0到9
数组的第二维四个数字,依次为(底的个位)^(幂%4)结果的个位。
*/
int myarr[10][4]={
{0, 0, 0, 0},
{1, 1, 1, 1},
{6, 2, 4, 8},
{1, 3, 9, 7},
{6, 4, 6, 4},
{5, 5, 5, 5},
{6, 6, 6, 6},
{1, 7, 9, 3},
{6, 8, 4, 2},
{1, 9, 1, 9},
};
return (myarr[di%10][mi%4]);
};
int main()
{
int di; int mi;
cout<<"Please input the ground: " ;
cin>>di;
cout<<"\n Please input the power: ";
cin>>mi;
cout<<"the Last digit is " << GetLastDigit_1(di, mi) <<endl;
cout<<"the Last digit is " << GetLastDigit_2(di, mi) <<endl;
return 0;
}
-----------------源代码结束------------
我很奇怪的是,为什么所有的数字如果它的指数是4n(n为自然数),无论n是多少其尾数都是同样的?
我的数学水平太差,不能证明。
因为只为自然数的4n次方结果的个位数为0,1,5,6才有可能保持(无论n是多少,乘幂的结果个位数不变)。那么10个数字(0到9)的4n次方,为什么个位数都落在这个范围内呢?
另外,我发现,第二个函数的数组中,第二列正好是0到9,这绝对不是巧合的。
或者,这个问题可以转化为:
假设m, n均为自然数,%为取余计算符,证明以下命题(不使用穷举法):
2009.7.5增加以下内容:
由于python里大数的计算自有支持,故添加一点:因此如果底与幂不同时超过1000,就打印出来。
print("本程序计算任选一个正整数的任意正整数次方的结果的尾数。\n")
EndList=[[0, 0, 0, 0], [1, 1, 1, 1], [6, 2, 4, 8], [1, 3, 9, 7], [6, 4, 6, 4],[5,5, 5, 5], [6, 6, 6, 6], [1, 7, 9, 3], [6, 8, 4, 2], [1, 9, 1, 9]]
g=int(input('请输入底数(正整数):\n'))
p=int(input('请输入指数(正整数):\n'))
print(g, "的", p, "次方,结果的个位数是 ",EndList[g %10][p %4])
if ((p>1000) or (g>1000)):
exit
else:
print ("完整结果如下:\n", g**p)
-------------------
我把这个问题发到了CSDN.net上,有一位网友提供了一个解法,但是我看不懂。
提供者: deng2000
试着给个证明,不知道算不算避免了穷举.先证明几个引理.
引理1
若整数a, b, c, d满足
a%10 = c%10
b%10 = d%10,
则 (a+b)%10 = (c+d)%10
(a*b)%10 = (c*d)%10
证明: 令a=10*A+m, c=10*C+m, b=10*B+n,d=10*D+n, 代人上式即得.
引理2
若 a%10 = b%10, 则对任意整数n,有
(a^n)%10 = (b^n)%10,
特别地,有
(a^n)%10 = ((a%10)^n)%10
证明:重复运用引理1的乘法部分即得
引理3
若a与10互素,则存在整数k,使得
(a*k)%10 = 1
证明: 因为a与10互素,由Eulid辗转相除法知,存在整数k,n使得
a*k + 10*n = 1
因此 (a*k)%10 = (1-10*n)%10 = 1%10 - (10*n)%10 = 1
引理4
对任意整数n,有
(2^(4n+1))%10 = 2
(5^(4n+1))%10 = 5
证明: 2^(4n+1)-2 = 2*(2^4n-1) = 2*(16^n-1)
= 2*(16-1)*(16^(n-1) + 16^(n-2) + ... + 16 + 1)
= 30 * (16^(n-1) + 16^(n-2) + ... + 16 + 1)
能被10整除
故(2^(4n+1))%10 = (2^(4n+1)-2+2)%10 = ((2^(4n+1)-2)%10 + 2)%10 = 2
同理可证 (5^(4n+1))%10 = 5
引理5
若整数a与10互素,则对任意整数n,有
(a^4n)%10 = 1
证明:我们知道,任意与10互素的数除以10的余数只有4种情况: 1, 3, 7, 9
考虑如下4个数:
a*1, a*3, a*7, a*9
因为a与10互素,这4个数也分别与10互素. 考虑这4个数除以10的余数,显然每个余数都只能在集合{1,3,7,9}中取值.我们还断言这4个余数是彼此不等的.如若不然,
设 (a*m)%10 = (a*n)%10 其中m,n是集合{1,3,7,9}中的两个不同的数,
运用引理3, 存在整数k使得 (a*k)%10=1, 在上式两边同乘以k,得:
(k*a*m)%10 = (k*a*n)%10
因此, ((k*a)%10 * m)%10 = ((k*a)%10 * n)%10
即 m%10 = n%10, 这与假设矛盾.
既然这4个余数彼此不等,又只能在集合{1,3,7,9}中取值,则这4个余数就是1,3,7,9按某一顺序的排列,因此
((a*1) * (a*3) * (a*7) * (a*9))%10 = (1*3*7*9)%10
亦即 (a^4 * (1*3*7*9))%10 = (1*3*7*9)%10
再运用引理3,存在整数p使得 (1*3*7*9*p)%10 = 1, 在上式两边同乘以p,即得
(a^4)%10 = 1
因此 (a^4n)%10 = ((a^4)^n)%10 = (1^n)%10 = 1
(顺便提一句, 引理5是初等数论中Euler定理的一个特例)
有了以上的引理,我们再来证明本命题: 对任意整数m,n,有
(m^4n)%10 = (m^(4*(n+1))%10 ----- (1)
(m^(4n+1))%10 = m%10 ----- (2)
证明: 令m=2^a*5^b*k, 其中a,b为整数,k是与10互素的整数
则 (m^(4n+1))%10 = ((2^a*5^b*k)^(4n+1))%10
= ((2^(4n+1))^a * (5^(4n+1))^b * k^(4n+1)) % 10
= (2^a * 5^b * k^4n * k) % 10
= (2^a * 5^b * k) % 10
= m%10
此即(2)式
下面证明(1)式
左边=(m^4n)%10=(m^(4(n-1)+4))%10 = (m^(4(n-1)+1+3))%10 = (m^(4(n-1)+1)*m^3)%10 = (m*m^3)%10 = (m^4)%10
右边=m^(4*(n+1))%10 = (m^(4n+1) * m^3)%10 = (m*m^3)%10 = (m^4)%10
故(1)式也成立
欢迎数学达人讨论讨论
Archiver|手机版|科学网 ( 京ICP备07017567号-12 )
GMT+8, 2024-11-25 12:53
Powered by ScienceNet.cn
Copyright © 2007- 中国科学报社