【NOIP2005普及组T4】循环-高精度
测试地址:循环
做法:两年了!!两年来,我数次挑战,屡败屡战,屡战屡败,终于在今天,终于把这题AC了!
好吧回归主题。我们设L(k)为尾k位的循环节长度,不难发现L(k)=mL(k-1),其中1≤m≤10,不难发现m为n^L(k-1),n^(2L(k-1)),...中第k位的循环节长度。因此,我们只需从小到大枚举位数now,然后在n^L(now-1),n^(2L(now-1)),...中找第now位的循环节长度,因为循环节长度≤10,所以如果枚举超过10次仍然没有出现循环,则表明无解,否则,最后的结果就是各位的m的乘积。
(其实明白了也并不怎么难嘛...)
以下是本人代码:
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
struct hp {int s[210];} n,a,b,ans;
char N[110];
int k,now,tmp;
void mult1(hp a,hp b,hp &c,int d)
{
hp s;
memset(s.s,0,sizeof(s.s));
for(int i=1;i<=d;i++)
for(int j=1;j<=d;j++)
s.s[i+j-1]+=a.s[i]*b.s[j];
for(int i=1;i<=d+1;i++)
if (s.s[i]>=10)
{
s.s[i+1]+=s.s[i]/10;
s.s[i]%=10;
}
c=s;
}
void mult2(hp a,int b,hp &c)
{
hp s;
memset(s.s,0,sizeof(s.s));
for(int i=1;i<=200;i++)
s.s[i]+=a.s[i]*b;
for(int i=1;i<=200;i++)
if (s.s[i]>=10)
{
s.s[i+1]+=s.s[i]/10;
s.s[i]%=10;
}
c=s;
}
int main()
{
scanf("%s%d",N,&k);
for(int i=strlen(N)-1,j=1;i>=0;i--,j++)
n.s[j]=N[i]-'0';
ans.s[1]=1;
a=n;
for(now=1;now<=k;now++)
{
b=n;
tmp=b.s[now];
int len=0;
do
{
mult1(a,b,b,k);
len++;
}while(len<10&&b.s[now]!=tmp);
if (b.s[now]!=tmp) {printf("-1");return 0;}
b=a;
for(int i=1;i<=len-1;i++) mult1(a,b,a,k);
mult2(ans,len,ans);
}
int out;
for(out=200;ans.s[out]==0;out--);
for(;out>=1;out--)
printf("%d",ans.s[out]);
return 0;
}