[NOIP2005 普及组] 循环 题解

题目描述

乐乐是一个聪明而又勤奋好学的孩子。他总喜欢探求事物的规律。一天,他突然对数的正整数次幂产生了兴趣。

众所周知,22 的正整数次幂最后一位数总是不断的在重复 2,4,8,6,2,4,8,6…2,4,8,6,2,4,8,6… 我们说 22 的正整数次幂最后一位的循环长度是 44(实际上 44 的倍数都可以说是循环长度,但我们只考虑最小的循环长度)。类似的,其余的数字的正整数次幂最后一位数也有类似的循环现象:

这时乐乐的问题就出来了:是不是只有最后一位才有这样的循环呢?对于一个整数 nn 的正整数次幂来说,它的后 kk 位是否会发生循环?如果循环的话,循环长度是多少呢?

注意:

  1. 如果 n 的某个正整数次幂的位数不足 k,那么不足的高位看做是 0。
  2. 如果循环长度是 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]);//输出
}

 在百忙之中写一篇题解也比较辛苦,别忘了点个赞!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值