我很久之前就思考过这个问题,但没有多想。
今天重新想起这个问题觉得非常有趣。
问题是这样的:
给你一个不超过六位小数的x
,求a√b + c = x
使其满足0 ≤ a√b,c < 1e9
,误差不超过1e-6
保证 0 ≤ x < 1e9
sample input
2.732050
sample output
√3 + 1
想了一会儿,想到了背包,复杂度O(1e6*8)
先贴代码,不知道以后有没有更好的思路
#include <bits/stdc++.h>
#define rep(a,b,c) for(int a=(b);a<=(c);a++)
#define get(x) (x-floor(x))
using namespace std;
const int MAXN = 1e6, MAXM = 1e6;
bool f[MAXM];
int g[MAXM], h[MAXM], fac[9] = {0, 1, 10, 100, 1000, 10000, 100000, 1000000, 10000000};
int dis(int a, int b)
{
if (a > b) swap(a, b);
return min(b - a, a - b + MAXM);
}
int Dp(int a, int b)
{
f[0] = true;
for (int i = 8; i >= 1; i--)
for (int j = 0; j <= MAXM; j++)
{
int k = (1ll * b * fac[i] + j) % MAXM;
if (f[j] && !f[k])
{
f[k] = true;
g[k] = j;
h[k] = fac[i];
}
}
int k = 0, ans = 0;
rep(j,1,MAXM) if (f[j] && dis(a, j) < dis(a, k))
k = j;
while (k)
{
ans += h[k];
k = g[k];
}
return ans;
}
int main()
{
double x;
scanf("%lf", &x);
double a = get(x * x) * MAXN, b = get(x * 2) * MAXN;
int c = Dp(a, b);
if (c > x) putchar('-');
printf("√%lld", (long long) ((x - c) * (x - c) + 0.5));
if (c != 0) printf(" + %d", c);
putchar('\n');
return 0;
}