循环数

题目描述

  142857是一个六位数,咱们发现:
  142857*1=142857
  142857*2=285714
  142857*3=428571
  142857*4=571428
  142857*5=714285
  142857*6=857142
  即用1到6的整数去乘142857,会获得一个将原来的数首尾相接循环移动若干数字再在某处断开而获得的数字。
  也就是说,若是把原来的数字和新的数字都首尾相接,他们获得的环是相同的。只是两个数的起始数字不必定相同。
  请写一个程序,判断给定的数不是循环数。java

1.1 输入描述:

  输入包括多组数据。
  每组数据包含一个正整数n,n是2到60位的正整数,而且容许前缀0。即001也是合法的输入数据。算法

1.2 输出描述:

  对应每一组数据,若是是循环数,则输出“Yes”;不然,输出“No”。数组

1.3 输入例子:

142857
012345

 

1.4 输出例子:

Yes
No

 

2 解题思路

  假设所求的数字为n,其为m位,则n能够表示为x_(m-1) x_(m-2)…x_0,由于n的位数比较多,可使用一个整形数组num来表示输入的值int数组的大小为m,num[i]= x_i。num中的每个下标表明一个数位。
  要求n是否为循环数,只要判断num乘以二、三、四、五、6是否都为循环数便可。假设num乘以k(k=二、三、四、五、6)后获得时的结果是ret,若是ret获得的结果的数据位数比num多,则num不是循环数,若是数据位数同样多,则对ret进行循环移动,找出移动后的数字ret^’使用得ret^’与num相等,若是不存说明num不是循环数。当k取完全部的数字后都相等,则num是循环数。等价n是循环数,不然n不是循环数。测试

3 算法实现

import java.util.Scanner;

/**
 * Declaration: All Rights Reserved !!!
 */
public class Main {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
//        Scanner scanner = new Scanner(Main.class.getClassLoader().getResourceAsStream("data.txt"));
        while (scanner.hasNext()) {
            String n = scanner.next();
            System.out.println(cycleNumber(n));
        }

        scanner.close();
    }

    /**
     * 判断n是否是循环数
     *
     * @param n 数字字符串
     * @return No:不是循环数,Yes:是循环数
     */
    private static String cycleNumber(String n) {

        int[] num = new int[n.length()];

        // 数字字符串转换成数组表示的数字
        // 下标由小到大表示低位到高位,
        for (int i = 0; i < n.length(); i++) {
            num[i] = n.charAt(n.length() - 1 - i) - '0';
        }

        //System.out.println(n + Arrays.toString(num));


        for (int i = 2; i <= 6; i++) {
            if (!check(num, i)) {
                return "No";
            }
        }

        return "Yes";
    }

    /**
     * 检查用数组表示的数字与n相乘,是不是循环数
     *
     * @param num 数组表示的数字,标由小到大表示低位到高位
     * @param n   数字
     * @return true:是循环数,false:不是循环数
     */
    private static boolean check(int[] num, int n) {

        // 来自低位的进位
        int carry = 0;
        // 结果数组
        int[] ret = new int[num.length];
        int t;

        for (int i = 0; i < num.length; i++) {
            t = carry + num[i] * n;
            ret[i] = t % 10;
            carry = t / 10;
        }

        // 计算以后还有一位说明相乘后结果多出一位,必定不循环数
        if (carry != 0) {
            return false;
        }

        // 将ret中的数字进行循环,构造新的ret,看是否与num相等
        for (int i = 0; i < ret.length; i++) {

            // 找要进行循环移动的位置
            if (num[0] == ret[i]) {
                exchange(ret, i);

                if (equal(ret, num)) {
                    return true;
                }

                // 若是不相等就还原
                exchange(ret, ret.length - i);
            }
        }


        return false;
    }

    /**
     * 将数组arr循环移动num位
     * num将数组arr分红[0, num-1]、[num, arr.length-1]两部分,先将[0, num-1]翻转
     * 再将[num, arr.length-1]翻转,最后将[0, arr.length-1]翻转可得结果
     *
     * @param arr 数组
     * @param num 移动的位数
     */
    private static void exchange(int[] arr, int num) {

        if (arr == null || num < 1 || num > arr.length) {
            return;
        }

        exchange(arr, 0, num - 1);
        exchange(arr, num, arr.length - 1);
        exchange(arr, 0, arr.length - 1);

    }

    /**
     * 将级数arr中从from到to位置的全部元素进行翻转
     *
     * @param arr  数组
     * @param from 开始位置
     * @param to   结束位置
     */
    private static void exchange(int[] arr, int from, int to) {
        if (arr == null || from < 0 || from > arr.length || to < 0 || to > arr.length) {
            return;
        }

        int t;
        while (from < to) {
            t = arr[from];
            arr[from] = arr[to];
            arr[to] = t;
            from++;
            to--;
        }
    }

    /**
     * 比较两个数组的内容是否相等
     *
     * @param a 数组
     * @param b 数组
     * @return true:相等,false:不相等
     */
    private static boolean equal(int[] a, int[] b) {
        if (a == null && b == null) {
            return true;
        }

        if (a == null || b == null || a.length != b.length) {
            return false;
        }

        for (int i = 0; i < a.length; i++) {
            if (a[i] != b[i]) {
                return false;
            }
        }

        return true;
    }
}

4 测试结果

这里写图片描述

相关文章
相关标签/搜索