1. 程式人生 > >二、最長的迴圈節

二、最長的迴圈節

1035 最長的迴圈節

10進位制的小數如果為無限迴圈小數,則存在一個迴圈節,求<=n的數中,倒數迴圈節長度最長的那個數,假如存在多個最優的答案,輸出所有答案中最大的那個數。 1/6= 0.1(6) 迴圈節長度為11/7= 0.(142857) 迴圈節長度為61/9= 0.(1) 迴圈節長度為1

迴圈小數的性質:

如果迴圈小數的每個迴圈節長度為偶數,(記為2K),那麼迴圈節中第i(1<=i<=k)個數字 + 第(i+k)個數字之和為9;

如果p是質數,並且d是1/p的迴圈節的位數,則d可以整除p−1;

如果1≤b<a, a沒有2或者5的質因數,並且a與b互質,那麼b/a的迴圈節位數等於:min{e∈N:10^e≡1(mod a)} 。

如果1≤b<a, a沒有2或者5的質因數,並且a與b互質,那麼b/a的迴圈節位數必整除ψ(a)(即a的尤拉函式)。

如果n,m≥3 2和5都不整除mn,並且n與m是互質的正整數,則1/mn的迴圈位數是1/n與1/m迴圈小數位數的最小公倍數;

…………,其他定理可以參考論文。

以下是學習筆記:

上面說到的第三條性質主要是用於求一個分數的迴圈節的長度,如果符合沒有2或者5的質因數,就利用上面公式求解,如果不符合就將2或者5的質因子提出然後利用上面的定理。

#include <stdio.h>
#include <iostream>
#include <cstring>
#include <algorithm>
#include <string.h>
#include <vector>

using namespace std;
const int Maxn = 1008;
struct table{
    int max_id;
    int max_val;
}note[Maxn];
int gcd(int a){
    int i=1;
    int p = 0;
    while(1){
        i = i*10%a;
        p++;
        if(i==1){
            return p;
        }
    }
}
int jian(int a){
    while(a%5==0){
        a = a/5;
    }
    while(a%2==0){
        a = a/2;
    }
    return a;
}
int n;
int main(){
    for(int i=0;i<Maxn;i++){
        note[i].max_id = note[i].max_val = 0;
    }
    note[10].max_id = 7;
    note[10].max_val = 6;
    while(~scanf("%d",&n)){
        if(note[n].max_id){
            printf("%d\n",note[n].max_id);
            continue;
        }
        for(int i=11;i<=n;i++){
            if(note[i].max_id!=0)
                continue;
            note[i].max_id = note[i-1].max_id;
            note[i].max_val = note[i-1].max_val;
            if(i%2==0||i%5==0){
                int temp = jian(i);
                if(temp==note[i].max_id){
                    note[i].max_id = temp;
                }
            }
            else{
                int temp = gcd(i);
                if(temp>=note[i].max_val){
                    note[i].max_val = temp;
                    note[i].max_id = i;
                }
            }
        }
        printf("%d\n",note[n].max_id);
    }
    return 0;
}