• 循环


    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
    算法分析

    可以发现,如果后k位循环,那么循环节一定是后k-1位循环的循环节的倍数

    >   证明如下:设后k位循环节为a1,后k-1位循环的循环节是a2,且a1=p*a2+b(p,b是常数)

    >     那么n^1的后k-1位=n^a2的后k-1位

    >      n^1的后k位=n^a1的后k位->n^1的后k-1位=n^a1的后k-1位

    >      所以n^a2的后k-1位等于n^a1的后k-1位...................................[1]

    >       因为b不是循环节,所以n^(p*a2)的后k-1位不等于n^(p*a2+b)的后k-1位

    >        n^(p*a2)的后k-1位等于n^a2的后k-1位

    >                所以n^a2的后k-1位不等于n^a1的后k-1位,这与[1]矛盾,

    >     所以我们可以求出后k-1位的循环节,再将后k-1位的循环节作为乘数求后k位的循环节(若n^a后k-1位与n的后k-1位相等,那么n^(a-1)为求后k位时的乘数),这样可以保证所枚举到的数一定是后k-1为循环节的倍数,而且可以大大减少枚举的数量

    >     可以通过记录后k位循环节长度是后k-1的循环节的多少倍来求循环节,这样,枚举的数就不需要用高精度,最后结果相乘时用高精度

    >   (2)整数的每一位有10种可能,如果某个长度枚举10次仍然没有循环的话,根据抽屉原理,因为这10个数中有1个没取到(就是该循环的一位)那么就一定出现了重复,也就是产生循环,但这个循环是以这9个数字中某个数开始的而不包括应该循环的那一位,那么意味着该循环的一位永远不会循环.那么这个时候就可以判断,这个数不会出现循环

    代码

    #include<iostream>
    #include<cstdio>
    #include<cstdlib>
    using namespace std;
    int k,kk;
    struct date{
    int x[10005];
    friend void read(date&a){
    char s[10005];
    int i,j;
    cin>>s;
    for(i=0;s[i];i++);
    for(i--,j=0;i>=0;i--,j++)a.x[j]=s[i]-'0';
    }
    date operator*(date&b){
    date c;
    for(int i=0;i<k;i++)for(int j=0;i+j<k;j++)
    c.x[i+j]+=x[i]*b.x[j];
    for(int i=0;i<k;i++){
    c.x[i+1]+=c.x[i]/10;
    c.x[i]%=10;
    }
    return c;
    }
    date operator*(int&b){
    for(int i=0;i<k;i++)x[i]*=b;
    for(int i=0;i<k;i++){
    x[i+1]+=x[i]/10;
    x[i]%=10;
    }
    return *this;
    }
    bool operator==(date&b){
    for(int i=0;i<=kk;i++)if(x[i]!=b.x[i])return false;
    return true;
    }
    date(){for(int i=0;i<=10005;i++)x[i]=0;}
    }c,s,n,ans;
    int main(){
    int i;
    read(n);
    scanf("%d",&k);
    // ans=s*n;
    // for(i=k;i&&!ans.x[i];i--);
    // for(i;i>=0;i--)printf("%d",ans.x[i]);
    ans.x[0]=1;
    for(kk=0;kk<k;kk++){
    c=n;
    for(i=1;;i++){
    s=c*n;
    if(s==n){n=c;ans=ans*i;break;}
    c=s;
    if(i>10){printf("-1");return 0;}
    }
    }
    for(i=k;i>0&&!ans.x[i];i--);
    for(i;i>=0;i--)printf("%d",ans.x[i]);
    }



  • 相关阅读:
    HDOj-1412
    HDOJ-2153
    HDOJ-1002
    紫书 例题 11-5 UVa 10048 (Floyd求最大权值最小的路径)
    紫书 例题11-4 UVa247 (Floyd判断联通)
    最短路模板
    紫书 例题 11-3 UVa 1151 (有边集的最小生成树+二进制枚举子集)
    紫书 例题 11-2 UVa 1395(最大边减最小边最小的生成树)
    紫书 例题 11-1 UVa 12219 (表达式树)
    紫书 习题 8-25 UVa 11175 (结论证明)(配图)
  • 原文地址:https://www.cnblogs.com/linzeli/p/7384824.html
Copyright © 2020-2023  润新知