二、最長的迴圈節
阿新 • • 發佈:2018-12-21
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; }