只是用来恢复状态,才做的水题,所以没什么好说的。
观察题目,可以得到
[left( 1 - dfrac{1}{2^{M + 1}}
ight) imes 2^{2^E - 1} = A imes 10^B
]
但是等式两边的值太大了,不好求值,于是我们可以取对数。
[lg left(1 - dfrac{1}{2^{M + 1}}
ight) + (2^E - 1) lg 2 = lg A + B
]
然而取对数之后算出来结果太小,误差很大,AC不了。所以我们还要用些其他技巧。
设式子左边的值为 (res),则 (10^{res} = C imes 10^D) ,其中 (0 < C < 10)。
显然 (0 < lg C < 1),所以 (D = lfloor res
floor) , $ C = 10 ^ {res - D}$ 。
比较一下 (A) 和 (C) , (B) 和 (D) 即可。
顺带一提,记得用sscanf
输入,注意$ eps $ 不能取太小,$ 10^{-4} $ 即可。
#include <cstdio>
#include <cstring>
#include <cmath>
#define MAX_M (9 + 5)
#define MAX_E (30 + 5)
using namespace std;
const double eps = 1e-4;
const double lg2 = log10(2);
double A;
int B;
int b[MAX_M][MAX_E];
double a[MAX_M][MAX_E];
char s[100];
int main()
{
double res;
for (int M = 0; M <= 9; ++M)
{
for (int E = 1; E <= 30; ++E)
{
res = log10(1.0 - 1.0 / (1 << M + 1)) + ((1 << E) - 1) * lg2;
b[M][E] = (int)res;
a[M][E] = pow(10, res - b[M][E]);
}
}
while (scanf("%s", s))
{
*strchr(s, 'e') = ' ';
sscanf(s, "%lf %d", &A, &B);
if (!A && !B) break;
for (int M = 0; M <= 9; ++M)
{
for (int E = 1; E <= 30; ++E)
{
if (b[M][E] != B || a[M][E] - A > eps || a[M][E] - A < -eps) continue;
printf("%d %d
", M, E);
goto NEXT;
}
}
NEXT:;
}
return 0;
}