循環數

題目描述

  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 測試結果

這裏寫圖片描述

相關文章
相關標籤/搜索