题目描述
乐乐是一个聪明而又勤奋好学的孩子。他总喜欢探求事物的规律。一天,他突然对数的正整数次幂产生了兴趣。
众所周知, 2 2 2的正整数次幂最后一位数总是不断的在重复 2 , 4 , 8 , 6 , 2 , 4 , 8 , 6 … 2,4,8,6,2,4,8,6… 2,4,8,6,2,4,8,6…我们说 2 2 2的正整数次幂最后一位的循环长度是 4 4 4(实际上 4 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 n n的正整数次幂来说,它的后 k k k位是否会发生循环?如果循环的话,循环长度是多少呢?
注意:
- 如果 n n n的某个正整数次幂的位数不足 k k k,那么不足的高位看做是 0 0 0。
- 如果循环长度是 L L L,那么说明对于任意的正整数 a , n a,n a,n的 a a a次幂和 a + L a+L a+L次幂的最后 k k k位都相同。
输入格式
一行,包含 2 2 2个整数 n ( 1 ≤ n < 1 0 100 ) n(1 \le n < 10^{100}) n(1≤n<10100))和 k ( 1 ≤ k ≤ 100 ) k(1 \le k \le 100) k(1≤k≤100), n n n和 k k k之间用一个空格隔开,表示要求 n n n的正整数次幂的最后 k k k位的循环长度。
输出格式
一个整数,表示循环长度。如果循环不存在,输出 − 1 -1 −1。
输入输出样例
输入 #1 复制
32 2
输出 #1 复制
4
说明/提示
对于 30 % 30\% 30%的数据, k ≤ 4 k \le 4 k≤4;
对于全部的数据, k ≤ 100 k \le 100 k≤100。
N O I P 2005 NOIP2005 NOIP2005普及组第四题
思路
首先,这道题一定是要高精度的,答案同样。
第一个方法肯定是暴力,知道循环,可是答案都要高精度了能不 T L E TLE TLE。
那么,正解就是这样的。
比如说 78910912 78910912 78910912 4 4 4 (第三个数据点)
取后面的四位就是 912 912 912
首先,我们可以求出最后一位的循环长度,很显然是 4 4 4。
2,4,8,6,2
^
接着,怎么求出后两位的循环长度呢,因为后两位要循环的话必须先让最后一位循环,再看第二位是否循环,那么直接每一次乘上个 4 4 4次 ( ( (就是 1 2 4 m o d 100 = 36 ) 12^4\bmod100=36) 124mod100=36),因为 4 4 4次个位才会循环,判断是否循环。
12,32,52,72,92,12
^
所以,后面两位要循环就要 20 20 20次,因为个位是一个小循环 4 4 4次,十位是在个位的基础上大循环 5 5 5次。
接下来求后面三位循环, 91 2 20 m o d 1000 = 176 912^{20}\bmod 1000=176 91220mod1000=176
912,512,112,712,312,912
^
五位一循环,所以,后三位的循环长度就是 20 × 5 = 100 20\times5=100 20×5=100
最后就是四位了
91 2 100 m o d 10000 = 3376 912^{100}\bmod 10000=3376 912100mod10000=3376
912,8912,6912,4912,2912,912
^
所以最终的答案就是 500 500 500
代码
#include<bits/stdc++.h>
#define cpy(x,y) for(int v=1;v<=k;v++)x[v]=y[v];
using namespace std;
int xh[11]={1,1,4,4,2,1,1,4,4,2};
int k,b[205],c[205],d[205],p[205],q[205],ans[205],tot1,tot2=2,t;
char a[105];
void mul1(int x[],int y[],int z[]){
for(int i=1;i<=k;i++){
for(int j=1;j<=k;j++){
z[i+j-1]+=x[i]*y[j];
z[i+j]+=z[i+j-1]/10;
z[i+j-1]%=10;
}
}
}
void mul2(int x[],int y,int z[]){
for(int i=1;i<=k;i++){
z[i]+=x[i]*y;
z[i+1]+=z[i]/10;
z[i]%=10;
}
}
int main(){
scanf("%s%d",a+1,&k);
int len=strlen(a+1);
for(int i=len;i>=len-k+1;i--)
c[++tot1]=a[i]-'0';
for(int i=1;i<=k;i++)
b[i]=c[i];
for(int i=1;i<xh[c[1]];i++){
memset(d,0,sizeof(d));//这个一定要加,如果放在mul1里面就会wa
mul1(b,c,d);
cpy(b,d);
}
ans[1]=xh[c[1]];
cpy(q,b);
cpy(p,b);
while(tot2<=k){
cpy(b,c);
while(t<11){
memset(d,0,sizeof(d));
mul1(b,p,d);
t++;
cpy(b,d);
if(b[tot2]==c[tot2])
break;
memset(d,0,sizeof(d));
mul1(q,p,d);
cpy(q,d);
}
if(t==11){//无解
printf("-1");
return 0;
}
cpy(p,q);
memset(d,0,sizeof(d));
mul2(ans,t,d);
for(int i=1;i<=100;i++)//计算答案
ans[i]=d[i];
tot2++;
t=0;
}
int anslen=101;
while(ans[anslen]==0&&anslen>1)
anslen--;
for(int i=anslen;i>=1;i--)
printf("%d",ans[i]);
return 0;
}
我最后只想说一句,那些用 p y t h o n , j a v a python,java python,java做的不知道比赛不支持吗?