• 【3004】循环数


    Time Limit: 3 second
    Memory Limit: 2 MB

    【问题描述】

        “循环数”指那些不包括数字0的没有重复数字的整数(比如81362),并且同时具有一个有趣的性质, 就像
    这个例子: 如果你从最左边的数字开始 (在这个例子中是8) 数从左边这个数字到右边 (如果数到了最右边,回
    到最左边), 你会停止在另一个新的数字 (如果没有停在一个不同的数字上,这个数就不是循环数)。就像: 
    
        8 1 3 6 2 从最左边接下去数8个数字: 1 3 6 2 8 1 3 6 所以下一个数字是6. 
        重复这样做 (这次从“6”开始数6个数字) 并且你会停止在一个新的数字上: 2 8 1 3 6 2,也就是2. 
        再这样做 (这次数两个): 8 1;
        再一次 (这次一个): 3; 
        又一次: 6 2 8 这时你回到了起点。
        所以81362是循环数。
    
    在从每一个数字开始数1次之后.如果你在从每一个数字开始数一次以后没有回到起点,你的数字不是一个循环数。 
    给你一个数字 M (在1到9位之间), 找出第一个比 M大的循环数, 并且一定能用一个无符号长整形数装下。 
    

    【输入】

    仅仅一行, M 的值

    【输出】

    仅仅一行,第一个比M大的循环数

    【输入样例】

    81361

    【输出样例】

    81362

    【题解】

    有更好的解法。但是我直接暴力模拟了。在代码里面说吧,太恶心了。有点复杂;

    【代码】

    #include <cstdio>
    #include <iostream>
    #include <string>
    
    using namespace std;
    
    string s1;
    bool bo[1000];
    int pret;
    
    void input_data()
    {
        cin >> s1;
    }
    
    void get_ans()
    {
        bool flag = false; //flag函数用于判断循环的出口
        int l = s1.size(); //获取数字的长度
        int t = 0;
        for (int i = 0;i <= l-1;i++) //先把输入的字符串转成整形数字
            t = t*10 + s1[i] - '0';
        pret = t; //pret是最初输入的数字
        int rest = l;
        while (!flag)
            {
                bool ok = true; //ok用于判断 有0 ,有重复数字的情况
                for (int i = 0;i <= l-1;i++) //判断是否有0
                    if (s1[i] == '0')
                        {
                            ok = false;
                            break;
                        }
                for (int i = 1;i <= 9;i++)
                    bo[i] = false;
                for (int i = 0;i <= l-1;i++) //用于判断是否有重复的数字
                    if (!bo[s1[i]-'0'])
                        bo[s1[i]-'0'] = true;
                            else
                                {
                                    ok = false;
                                    break;
                                }
                if (ok) //如果以上情况都未出现就试试这个数是否为循环数 也还好 才40行左右
                {
                    int j = 0; //j表示现在到数字各个数字的指针
                    int k = s1[0] - '0'; //k表示接下来要走几步
                    for (int i = 0;i <= l-1;i++) //用于判断是否到了之前已经走过的地方
                        bo[i] = true;
                    bo[j] = false; //初始位置已经走过了
                    rest --;//rest用于记录剩余的数字
                    flag = true;
                    for (int mm = 1;mm <= l;mm++) //表示要检验的次数 ,检验l-1次时所有数字都被走过,当走第l次时,检验能否回到原点。
                        {
    
                            for (int i = 1;i <= k;i++) //先跳k步
                                {
                                    j++;
                                    if (j > (l-1)) j = 0;
                                }
                            if (!bo[j] && rest!=0) //如果遇到了之前跳到的数字,就判断一下是否已经没有剩余数字
                                {
                                    flag = false;
                                    break;
                                }
                            if (!bo[j] && j!=0) //又或者回到了第一次扫描的位置
                                {
                                    flag = false;
                                    break;
                                }
                            bo[j] = false; //如果这个数字之前没出现过 现在就标记下
                            rest--; //剩余的数字递减
                            k = s1[j] - '0'; //获取下一个需要循环的次数
                        }
                    if (t == pret) flag = false; //因为是大于输入的数字 所以不能和输入数字相同
                    if (flag == true) //如果以上约束都过了 就可以了 输出就好
                        {
                            printf("%d
    ",t);
                            return;
                        }
                }
                t++; //尝试下一个数字 直接递增
                string ts;
                int ll = 0;
                int tt = t;
                while (tt > 0) //tt用于把数字转化成string类 存在ts字符串中。
                    {
                        ts[++ll] = (tt % 10) + '0';
                        tt = tt / 10;
                    }
                for (int i = ll;i >= 1;i--)//这样存是倒序的,所以再把它正序下。
                    s1[ll-i] = ts[i];
                rest = ll; //更新剩下的数字
                l = ll;//更新数字的长度
            }
    }
    
    int main()
    {
        input_data();
        get_ans();
        return 0;
    }
    


     【代码2更优秀的解法,pascal版】

    这个程序直接用数组记录某个数是否可以由其他数字i通过走a[i]步走到。如果所有的位置都能通过其他位置通过走x步到,那就是一个循环数。要注意死循环的情况排除掉,比如12

    1->2 ,但是2 会一直到2,不能到1.这种情况要排除。

    var n:longint;
        a,b:array[1..100] of integer;
    function yes:boolean;
     var s:string;l,i:integer;
     begin str(n,s);
           if pos('0',s)>0 then exit(false);
           l:=length(s);
           for i:=1 to l do val(s[i],a[i]);
           fillchar(b,sizeof(b),0);
           for i:=1 to l do
             begin inc(b[a[i]]);
                   if b[a[i]]>1 then exit(false); end;
           fillchar(b,sizeof(b),0);
           for i:=1 to l do
             begin if (i+a[i]-1)mod l+1=i then exit(false);
                   inc(b[(i+a[i]-1)mod l+1]); end;
           for i:=1 to l do if b[i]=0 then exit(false);
           yes:=true; end;
    begin
      readln(n);
      inc(n);
      while not yes and (n<maxlongint) do inc(n);
      writeln(n);
    end.
    


     

  • 相关阅读:
    cast() 函数进行类型转换
    '+' 拼接字符串引起的小事故
    shell统计ip访问情况并分析访问日志
    Windows 环境上域名配置
    WebApi中Route的作用
    Postman测试WebApi使用总结
    C# VS2017新建WepApi
    C# 反射总结
    winform--同一个项目窗体复制
    winform TextBox设置透明
  • 原文地址:https://www.cnblogs.com/AWCXV/p/7632454.html
Copyright © 2020-2023  润新知