[NOIP2005] 普及组 循环

陶陶摘苹果

校门外的树

采药

以上三道都不是重点

 

循环

 

题目描述

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

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

循环 循环长度

2 2、4、8、6

4

3 3、9、7、1

4

4 4、6 2

5 5 1

6 6 1

7 7、9、3、1

4

8 8、4、2、6

4

9 9、1 2

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

注意:

1. 如果n的某个正整数次幂的位数不足k,那么不足的高位看做是0。

2. 如果循环长度是L,那么说明对于任意的正整数a,n的a次幂和a + L次幂的最后k位都相同。

输入输出格式

输入格式:

 

输入文件circle.in只有一行,包含两个整数n(1 <= n < 10^100)和k(1 <= k <= 100),n和k之间用一个空格隔开,表示要求n的正整数次幂的最后k位的循环长度。

 

输出格式:

 

输出文件circle.out包括一行,这一行只包含一个整数,表示循环长度。如果循环不存在,输出-1。

 

输入输出样例

输入样例#1:
32 2
输出样例#1:
4

说明

对于30%的数据,k <= 4;

对于全部的数据,k <= 100。

NOIP2005普及组第四题

 

依照题意累乘,设原数是n,假设乘了x次后,最后一位(第L位)的数与最开始相同了,那么就要开始计算倒数第二位(L-1位)的循环节。

由于L位至少要乘x次才能循环,所以算L-1位时,至少要乘n^x次才能让L位再重复(L-1位循环而L位不同是没有意义的)。

以此类推,每找到一层循环,在找下一层时就可以每次直接乘n^x^y^...,运行效率会高很多。

具体实现要用到高精度。

 

这代码估计是高精乘法常数写挂了,用时近1000ms

 1 #include<iostream>  
 2 #include<cstring>  
 3 #include<cmath>  
 4 #include<cstdio>  
 5 using namespace std;  
 6 int t=1;  
 7 unsigned int n=0,k;
 8 unsigned int xh[200];
 9 int num;//记录有多少层
10 char s[200];
11 bool flag=0,flag2=0;
12 struct node{  
13     unsigned int v[200];  
14     int s;  
15 }a,b,c,bas,ans,nn;
16 node multiple(const node a1,const node b1){ //高精度乘法部分   
17     int i,j,x=0;  
18     if(a1.s==1&&a1.v[0]==0)return a1;  
19     if(b1.s==1&&b1.v[0]==0)return b1;    
20     node c1={0};  
21     for(i=0;i<=100 && i<a1.s;i++){  
22         for(j=0;j<=100 && j<b1.s;j++){  
23             c1.v[i+j]+=a1.v[i]*b1.v[j];  
24             c1.v[i+j+1]+=c1.v[i+j]/10;  
25             c1.v[i+j]%=10;  
26         }  
27         c1.s=i+j;  
28         if(c1.v[i+j]!=0)c1.s++;  
29     }  
30     if(c1.s>k) c1.s=k+1;  
31     return c1;  
32 } 
33 
34 int main(){  
35     int i,j;  
36     scanf("%s%d",s,&k);
37     c.s=strlen(s);
38     ans.v[0]=1;
39     ans.s=1;
40     for(i=0;i<c.s;i++) c.v[i]=s[c.s-i-1]-'0'; 
41     bas=c;//原数备份,用作比较 
42     a=c;
43     b=c; 
44     int k1;
45     for(k1=0;k1<k;k1++){
46         num=0;
47         b=bas;
48 //        c=bas;
49         do{
50             b=multiple(a,b);
51             num++;
52         }while(num<10 && b.v[k1]!=bas.v[k1]);
53         if(bas.v[k1]!=b.v[k1]){
54             printf("-1");
55             return 0;
56         }
57         b=a;
58         for(j=0;j<num-1;j++)
59              a=multiple(a,b);
60          
61         nn.s=1;
62         nn.v[0]=num;
63         ans=multiple(ans,nn);
64     }
65     i=100;
66     while(ans.v[i]==0)i--;
67     for( ;i>=0;i--)printf("%d",ans.v[i]);
68     return 0;  
69 }  

 

posted @ 2016-10-27 17:25  SilverNebula  阅读(1137)  评论(0编辑  收藏  举报
AmazingCounters.com