Codeforces-984-C(簡單數論)
阿新 • • 發佈:2018-11-15
Codeforces 984C - Finite or not?
題目原址
[http://codeforces.com/contest/984/problem/C]
註明:本篇部分參考
[https://blog.csdn.net/yo_bc/article/details/80342521]
題意
給三個數 p,q,b,判斷 在 b 進位制當中的小數部分是否有限。
題解
- 將一個十進位制小數 (
的整數部分轉換為 b 進位制不會變成小數 ) 轉換為 b 進位制的小數形式,用累積相乘
- 由尤拉的整數唯一分解法,對於任意不是1的正整數 q 有: 所以當 q 中的所有質因數都是 b 中的質因數時,上方程有解。
- 其實 gcd (求最大公因式)函式,就是找出兩數共有的每一個質因數當中指數較小的一個,並把他們相乘。
所以q 除以 gcd 的過程就是去掉 q 中的一些質數,但知若 q 中質因數不在 b 中,那麼最後 q 總不能為 1 ,並且最後 gcd 為1。反之,若 q 為 1 了,說明 q 中的質因數都在 b 中了。 - 最後補充一個小優化,在每次 q 除以 gcd 時,除多幾次,直至不能整除為止。
實現
#include <stdio.h>
typedef long long ll;
ll gcd(ll x , ll y) {
if (!y) return x;
else return gcd(y, x%y);
}
int main() {
int n;
scanf("%d", &n);
ll a, b, nota;
while (n--) {
scanf("%lld %lld %lld", &a, &b, ¬a);
b /= gcd(a, b);//約分
while (b != 1 || 0*printf("Finite\n")) {//b被約分完了,輸出右邊並結束
nota = gcd(b, nota);
if (nota == 1 && printf("Infinite\n"))//nota被榨乾了
break;
while (b % nota == 0)//b還能被整除
b /= nota;
}
}
}
實現優化1(18/11/13)
#include <stdio.h>
typedef long long ll;
ll gcd(ll x , ll y) {
return y==0 ? x : gcd(y,x%y);
}
int main() {
int n;
scanf("%d", &n);
ll a, b, nota,tmp;
while (n--) {
scanf("%lld %lld %lld", &a, &b, ¬a);
b /= gcd(a, b);
while ((tmp = gcd(b,nota))!= 1)//tmp還能再戰時
while (b % nota == 0)//b能被約時
b /= nota;
puts(b==1?"Finite":"Infinite");//puts自帶\n
}
}
注意:1. = 優先順序低於 != 2. puts()自帶換行符
錯誤思考
迴圈小數的迴圈部分總是從第 1 位到第 n 位,如: 但其實有:
錯誤程式碼
#include <stdio.h>
typedef long long ll;
int main() {
int n;
scanf("%d", &n);
while (n--) {
ll a, b, nota;
scanf("%lld %lld %lld", &a, &b, ¬a);
ll tmp = (a %= b);
if (!tmp && printf("Finite\n"))//a本來就能被b整除
continue;
do {
a = (a*nota) % b;//累積相除後的餘數
if (tmp == a && printf("Infinite\n"))
break;
}
while (a||0*printf("Finite\n"));//餘數不是0時
}
}