题目描述
乐乐是一个聪明而又勤奋好学的孩子。他总喜欢探求事物的规律。一天,他突然对数的正整数次幂产生了兴趣。
众所周知,22 的正整数次幂最后一位数总是不断的在重复 2,4,8,6,2,4,8,6…2,4,8,6,2,4,8,6… 我们说 22 的正整数次幂最后一位的循环长度是 44(实际上 44 的倍数都可以说是循环长度,但我们只考虑最小的循环长度)。类似的,其余的数字的正整数次幂最后一位数也有类似的循环现象:
这时乐乐的问题就出来了:是不是只有最后一位才有这样的循环呢?对于一个整数 nn 的正整数次幂来说,它的后 kk 位是否会发生循环?如果循环的话,循环长度是多少呢?
注意:
- 如果 n 的某个正整数次幂的位数不足 k,那么不足的高位看做是 0。
- 如果循环长度是 L,那么说明对于任意的正整数 a,n的 a 次幂和 a+L 次幂的最后 k 位都相同。
输入格式
共一行,包含两个整数 n 和 k。n 和 k 之间用一个空格隔开,表示要求 nn 的正整数次幂的最后 kk 位的循环长度。
输出格式
一个整数,表示循环长度。如果循环不存在,输出 −1。
输入输出样例
输入 #1
32 2
输出 #1
4
为什么各位的代码都那么长?我的代码没压行才40行,比Python都短
个人高精推荐用结构体,可以作为函数返回值,而且不用memset直接赋值就可以清空,似乎还比数组版跑得快
这道题思路很简单,就是逐位比较,主要的难点是代码实现部分
详细注释代码如下:
#include<cstdio>
#include<cstring>
char c[109];
int k,l,u;
struct big{
int a[109];
}d,p,q,r,s,t;//结构体
big mul(big x,big y){//高精乘高精
big z=d;//赋值实现清空
register int i,j;
for(i=1;i<=k;++i){
for(j=k-i+1;j;--j){
z.a[i+j-1]+=x.a[i]*y.a[j];
}
}//高精乘法
for(i=1;i<k;++i)z.a[i+1]+=z.a[i]/10,z.a[i]%=10;
z.a[k]%=10;//处理进位
return z;
}
int main(){
register int i,j;
scanf("%s%d",c,&k),l=strlen(c);
for(i=(l<k?l:k);i;--i)p.a[i]=c[l-i]-48;//字符串转整数,p即为原数
r=p,t.a[l=1]=1;//r为乘的结果,初始值为p
for(i=1;i<=k;++i){
if(mul(p,r).a[i]==p.a[i])continue;//周期为1的情况
u=1,s=r;//s为每次乘的数
do{
r=mul(s,r),++u;
if(u>10){
puts("-1");//判无解
return 0;
}
}while(mul(p,r).a[i]!=p.a[i]);
for(j=1;j<=l;++j)t.a[j]*=u;
for(j=1;j<l;++j)t.a[j+1]+=t.a[j]/10,t.a[j]%=10;
if(t.a[l]>=10)t.a[l+1]+=t.a[l]/10,t.a[l++]%=10;//更新答案,高精乘单精
}
for(i=l;i;--i)printf("%d",t.a[i]);//输出
}
在百忙之中写一篇题解也比较辛苦,别忘了点个赞!