UVA 202
题目的大致意思是给出有理数的分子和分母,要你找到化为循环小数后的循环节。
在此仅仅讨论有循环节非0的情况
给定分子a,分母b,假若没想到最多需要做除法的次数,可以用vector之类的玩意。
以下是我没有想到的地方:
原理:抽屉原理
a被b除,余数一共有b种可能(0 ~ b-1),当我在做第b+1次除法的时候,在这b+1个余数中一定会至少有重复的一对。
我的做法是把每一次的商和余数作为一个结构体来储存,开了一个3010的数组,每一次计算后和之前数组里面的相比较
感觉用到抽屉原理很不错,以前没有这样想过。
自己的代码感觉仍然有些繁琐
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
struct Node{
int quotient, remain;
bool friend operator==(const Node& a, const Node& b){
return a.quotient == b.quotient&&a.remain == b.remain;
}
}ans[3010];
int ans_length;
int main(){
ios_base::sync_with_stdio(false);
int n, m, num, k; bool flag = false;
Node test, *pn = nullptr;
while (cin >> n >> m){
num = n / m, k = n%m;
if (k == 0)
flag = true;
else{
while (k != 0){
k *= 10, test.quotient = k / m, test.remain = k%m, k %= m;
pn = find(ans, ans + ans_length, test);
if (ans + ans_length != pn)
break;
else
ans[ans_length++] = test;
}
}
cout << n << '/' << m << " = " << num << ".";
if (k == 0){
for (int i = 0; i < ans_length - 1; ++i)
cout << ans[i].quotient;
if (!flag)
cout << test.quotient;
cout<< "(0)\n 1 = number of digits in repeating cycle\n";
}
else{
if (ans_length>50){
for (int i = 0; ans + i != pn; ++i)
cout << ans[i].quotient;
cout << "(";
for (Node* pi = pn; pi-ans<50; ++pi)
cout << pi->quotient;
cout << "...)\n " << ans + ans_length - pn << " = number of digits in repeating cycle\n";
}
else{
for (int i = 0; ans + i != pn; ++i)
cout << ans[i].quotient;
cout << "(";
for (Node* pi = pn; pi != ans + ans_length; ++pi)
cout << pi->quotient;
cout << ")\n " << ans + ans_length - pn << " = number of digits in repeating cycle\n";
}
}
cout << endl;
ans_length = 0; flag = false;
}
return 0;
}
UVA 11809
考虑到数据的范围,A∈(0,10),M∈(0,10),E ∈[1,30],数据量并不是很大,很自然的考虑打表,然后在表中查询,关键是怎么生成表的问题。
0.1111111(M+1个)* 2^(2^E-1) = A*10^B
这个公式是我最开始想到的打表的依据,可是后来发现E最大可以到30,double是存不下的。
以下是我没有想到的地方
两边可以取对数,因为在计算左边的时候,M和E是我们穷举的,因此左边的值是已知的,不妨另左边的值为k
lgk = lg A + B
变成这样的式子,只需要通过强制转换提取整数部分算出B,然后相减提取小数部分就算出A 了
以下是代码
#include<cstdio>
#include<cmath>
#include<cstring>
using namespace std;
const double lg2 = log10(2), accuracy = 1e-5;
double mantissa[10][31];
long long num[10][31];
char con[100];
int main(){
double a, b, c;
long long d;
for (int i = 0; i < 10;++i)
for (int j = 1; j <= 30; ++j){
a = log10(1 - pow(0.5, i + 1)), b = lg2*((1 << j) - 1), c = a + b;
num[i][j] = (long long)c, mantissa[i][j] = pow(10, c - num[i][j]);
}
while (scanf("%s", con)){
if (strlen(con) == 3)
break;
con[17] = ' ';
sscanf(con, "%lf%lld", &a, &d);
for (int i = 0; i < 10; ++i)
for (int j = 1; j <= 30; ++j)
if (num[i][j] == d && ((fabs(a - mantissa[i][j]) < accuracy) || (fabs(a / 10 - mantissa[i][j]) < accuracy)))
printf("%d %d\n", i, j), j = 31, i = 10;
}
return 0;
}