洛谷P1050循环题解--zhengjun
题目描述
乐乐是一个聪明而又勤奋好学的孩子。他总喜欢探求事物的规律。一天,他突然对数的正整数次幂产生了兴趣。
众所周知,\(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\)位是否会发生循环?如果循环的话,循环长度是多少呢?
注意:
- 如果\(n\)的某个正整数次幂的位数不足\(k\),那么不足的高位看做是\(0\)。
- 如果循环长度是\(L\),那么说明对于任意的正整数\(a,n\)的\(a\)次幂和\(a+L\)次幂的最后\(k\)位都相同。
输入格式
一行,包含\(2\)个整数\(n(1 \le n < 10^{100})\))和\(k(1 \le k \le 100)\),\(n\)和\(k\)之间用一个空格隔开,表示要求\(n\)的正整数次幂的最后\(k\)位的循环长度。
输出格式
一个整数,表示循环长度。如果循环不存在,输出\(-1\)。
输入输出样例
输入 #1 复制
32 2
输出 #1 复制
4
说明/提示
对于\(30\%\)的数据,\(k \le 4\);
对于全部的数据,\(k \le 100\)。
\(NOIP2005\)普及组第四题
思路
首先,这道题一定是要高精度的,答案同样。
第一个方法肯定是暴力,知道循环,可是答案都要高精度了能不\(TLE\)。
那么,正解就是这样的。
比如说\(78910912\) \(4\) (第三个数据点)
取后面的四位就是\(912\)
首先,我们可以求出最后一位的循环长度,很显然是\(4\)。
2,4,8,6,2
^
接着,怎么求出后两位的循环长度呢,因为后两位要循环的话必须先让最后一位循环,再看第二位是否循环,那么直接每一次乘上个\(4\)次\((\)就是\(12^4\bmod100=36)\),因为\(4\)次个位才会循环,判断是否循环。
12,32,52,72,92,12
^
所以,后面两位要循环就要\(20\)次,因为个位是一个小循环\(4\)次,十位是在个位的基础上大循环\(5\)次。
接下来求后面三位循环,\(912^{20}\bmod 1000=176\)
912,512,112,712,312,912
^
五位一循环,所以,后三位的循环长度就是\(20\times5=100\)
最后就是四位了
\(912^{100}\bmod 10000=3376\)
912,8912,6912,4912,2912,912
^
所以最终的答案就是\(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;
}
我最后只想说一句,那些用\(python,java\)做的不知道比赛不支持吗?