【题目链接】
OpenJudge NOI 1.13 49:计算对数
【题目考点】
1. 高精度
2. 枚举
【解题思路】
解法1:枚举
由于题目中说了,x不大于20,所以只需要枚举20以内的x,看取哪一个x时满足
a
x
≤
b
<
a
x
+
1
a^x\le b < a^{x+1}
ax≤b<ax+1即可。 这里需要高精度数字比较、高精度乘高精度。 a最多100位,x最高20,得到的数字
a
x
+
1
a^{x+1}
ax+1最大不会超过2100位。 记n为数字a的位数,该算法复杂度为:
O
(
n
x
+
1
)
O(n^{x+1})
O(nx+1)
解法2:二分
假设x可以很大,那么需要用二分查找来确定x的值。使用快速幂来求
a
x
a^x
ax。 设l为1,r为20,每次循环取到中点m。
- 如果
a
m
+
1
≤
b
a^{m+1} \le b
am+1≤b,说明m取小了,l应该右移。
- 如果
b
<
a
m
b < a^m
b<am,说明m取大了,r应该左移。
- 如果
a
m
≤
b
<
a
m
+
1
a^m\le b < a^{m+1}
am≤b<am+1,说明找到了目标数值。
该算法的复杂度为
O
(
l
o
g
x
?
l
o
g
x
?
n
)
O(logx\cdot logx\cdot n)
O(logx?logx?n)
【题解代码】
解法1:枚举
#include <bits/stdc++.h>
using namespace std;
#define N 2105
void toNum(char s[], int a[])
{
a[0] = strlen(s);
for(int i = 1; i <= a[0]; ++i)
a[i] = s[a[0]-i] - '0';
}
void numCpy(int a[], int b[])
{
for(int i = 0; i <= b[0]; ++i)
a[i] = b[i];
}
void multi(int a[], int b[])
{
int r[N] = {};
for(int i = 1; i <= a[0]; ++i)
{
int c = 0;
for(int j = 1; j <= b[0]; ++j)
{
r[i+j-1] += c + a[i] * b[j];
c = r[i+j-1] / 10;
r[i+j-1] %= 10;
}
r[b[0]+i] += c;
}
int ri = a[0] + b[0];
while(r[ri] == 0 && ri > 1)
ri--;
r[0] = ri;
numCpy(a, r);
}
int numCmp(int a[], int b[])
{
if(a[0] > b[0])
return 1;
else if(a[0] < b[0])
return -1;
else
{
for(int i = a[0]; i >= 1; --i)
{
if(a[i] > b[i])
return 1;
else if(a[i] < b[i])
return -1;
}
return 0;
}
}
char s1[N], s2[N];
int a[N], b[N], l[N], r[N];
int main()
{
cin >> s1 >> s2;
toNum(s1, a);
toNum(s2, b);
r[0] = 1, r[1] = 1;
for(int x = 0; x <= 20; ++x)
{
numCpy(l, r);
multi(r, a);
if(numCmp(b, l) >= 0 && numCmp(r , b) > 0)
{
cout << x;
return 0;
}
}
return 0;
}
#include<bits/stdc++.h>
using namespace std;
#define N 2105
struct HPN
{
int a[N];
HPN()
{
memset(a, 0, sizeof(a));
}
HPN(string s)
{
memset(a, 0, sizeof(a));
a[0] = s.length();
for(int i = 1; i <= a[0]; ++i)
a[i] = s[a[0]-i] - '0';
}
int& operator [] (int i)
{
return a[i];
}
void operator *= (HPN b)
{
HPN r;
for(int i = 1; i <= a[0]; ++i)
{
int c = 0;
for(int j = 1; j <= b[0]; ++j)
{
r[i+j-1] += c + a[i] * b[j];
c = r[i+j-1] / 10;
r[i+j-1] %= 10;
}
r[b[0]+i] += c;
}
int ri = a[0] + b[0];
while(r[ri] == 0 && ri > 1)
ri--;
r[0] = ri;
*this = r;
}
int numCmp(int a[], int b[])
{
if(a[0] > b[0])
return 1;
else if(a[0] < b[0])
return -1;
else
{
for(int i = a[0]; i >= 1; --i)
{
if(a[i] > b[i])
return 1;
else if(a[i] < b[i])
return -1;
}
return 0;
}
}
bool operator >= (HPN b)
{
return numCmp(a, b.a) >= 0;
}
bool operator > (HPN b)
{
return numCmp(a, b.a) > 0;
}
};
int main()
{
string s1, s2;
cin >> s1 >> s2;
HPN a(s1), b(s2), l, r("1");
for(int x = 0; x <= 20; ++x)
{
l = r;
r *= a;
if(b >= l && r > b)
{
cout << x;
return 0;
}
}
return 0;
}
解法2:二分
#include<bits/stdc++.h>
using namespace std;
#define N 2105
struct HPN
{
int a[N];
HPN()
{
memset(a, 0, sizeof(a));
}
HPN(string s)
{
memset(a, 0, sizeof(a));
a[0] = s.length();
for(int i = 1; i <= a[0]; ++i)
a[i] = s[a[0]-i] - '0';
}
int& operator [] (int i)
{
return a[i];
}
void setLen(int i)
{
while(a[i] == 0 && i > 1)
i--;
a[0] = i;
}
HPN operator * (HPN b)
{
HPN r;
for(int i = 1; i <= a[0]; ++i)
{
int c = 0;
for(int j = 1; j <= b[0]; ++j)
{
r[i+j-1] += a[i]*b[j] + c;
c = r[i+j-1] / 10;
r[i+j-1] %= 10;
}
r[i+b[0]] += c;
}
r.setLen(a[0] + b[0]);
return r;
}
HPN operator ^ (int b)
{
HPN c = *this, r("1");
while(b > 0)
{
if(b % 2 == 1)
r = r * c;
c = c * c;
b /= 2;
}
return r;
}
int numCmp(int a[], int b[])
{
if(a[0] > b[0])
return 1;
else if(a[0] < b[0])
return -1;
else
{
for(int i = a[0]; i >= 1; --i)
{
if(a[i] > b[i])
return 1;
else if(a[i] < b[i])
return -1;
}
return 0;
}
}
bool operator >= (HPN b)
{
return numCmp(a, b.a) >= 0;
}
bool operator < (HPN b)
{
return numCmp(a, b.a) < 0;
}
};
int main()
{
string s1, s2;
cin >> s1 >> s2;
HPN a(s1), b(s2);
int l = 0, r = 20, m;
while(l <= r)
{
m = (l + r) / 2;
if(b >= (a^(m+1)))
l = m + 1;
else if(b < (a^m))
r = m - 1;
else
{
cout << m;
return 0;
}
}
return 0;
}
|