有限小数,进制转换,思维
Problem:G
Time Limit:1000ms
Memory Limit:65535K
Description
给定一个 A 进制下的分数 a/b, 小蓝想把它化为 B 进制下的小数 c。 现在他想知道这个小数是不是一个有限小数。
Input
输入共一行,包含四个数 a, b, A, B,表示该分数和两种进制。 其中 A, B 使用十进制表示, a, b 中大于 9 的数字使用大写字母表示, A 表示 10,B 表示 11,以此类推。
Output
输出一行,包含一个字符串。 如果该小数是一个有限小数,则输出 "Yes"; 否则输出 "No"(不包含引号)。
Sample Input
10 11 10 11
Sample Output
Yes
Hint
对于 20% 的评测用例,A = B = 10。 对于所有评测用例,0 <= a < b <= 10^9, 2 <= A, B <= 36(数为十进制)。
解析:
本题需要用到数字逻辑的小数的进制转换知识,举个例子:将0.3转换成2进制小数
0.3 * 2 = 0.6———————0
0.6 * 2 = 1.2———————1
0.2 * 2 = 0.4———————0
0.4 * 2 = 0. ———————0
0.8 * 2 = 1.6———————1
0.6 * 2 = 1.2———————1
0.2 * 2 = 0.4———————0
0.4 * 2 = 0.8———————0
取8位小数的话0.3 = 0.01001100
转换成B进制只需要将上面的2换成B即可
这样,将 a/b 转换成B进制只需
令 Y=a/b
将 Y*B^k ,k按保留的位数取
所以这道题我们只需将 k 取得很大,再看最后Y是否为零即可判断出它是否能被b整除,
这里 a*B^k 可能会很大,所以我们呢可以一边乘一边对 b 取模
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<string>
#include<cstring>
#include<cmath>
#include<ctime>
#include<algorithm>
#include<utility>
#include<stack>
#include<queue>
#include<vector>
#include<set>
#include<map>
#include<unordered_map>
using namespace std;
typedef long long LL;
const int N = 1e7 + 5;
LL a, b, A, B;
string sa, sb;
LL F(string x) {
LL ret = 0;
int len = x.length();
LL t = 1;
for (int i = len - 1; i >= 0; i--) {
if (x[i] >= '0' && x[i] <= '9') {
ret += (x[i] - '0') * t;
}
else {
ret += (x[i] - 'A' + 10) * t;
}
t *= A;
}
return ret;
}
int main() {
cin >> sa >> sb >> A >> B;
a = F(sa);
b = F(sb);
a %= b;
for (int i = 1; i <= N&&a; i++) {
a *= B;
a %= b;
}
if (a == 0) {
cout << "Yes" << endl;
}
else {
cout << "No" << endl;
}
return 0;
}