P2759 奇怪的函数 题解
前置知识:
二分,对数。
简要题意:
求 \(x^x\) 的位数超过或达到 \(n\) 位的最小的 \(x\).
\(n \leq 2 \times 10^9\).
首先,\(x^x\) 与 \(x\) 是正比例关系,具有单调性。朴素来说就是 \(x^x\) 随 \(x\) 增大而增大,主要因为 \(x>1\).(答案不可能是 \(1\) 啊)
具有单调性的函数可以进行 二分答案。 可以用 \(\mathcal{O}(\log n)\) 的时间(其实不到 \(\log\),因为 \(x^x\) 位数大于 \(n\) 答案应该比 \(n\) 小的多,但是数据范围就一个 \(n\),这样分析也没啥问题)。那么如何验证答案呢?
即已知 \(x\) 和 \(n\),如何判断 \(x^x\) 的位数是否超过 \(n\)?
下面我们要说一个函数,可以算出一个数的位数。
假设要算 \(a\) 的位数,同时存在 自然数 \(k\) 使得 \(10^k \leq a < 10^{k+1}\),则 \(a\) 是 \(k+1\) 位数。简单来说,就是,在 \(10^3\) 和 \(10^4\) 之间除了 \(10^4\) 都是 \(4\) 位数,很显然吧!
你会发现 \(\log_{10} 10^k = k , \log_{10} 10^{k+1} = k+1\),所以,\(\lfloor \log_{10} a \rfloor= k\) .
这样你会发现,\(\lfloor \log_{10} a \rfloor + 1\) 就是 \(a\) 的位数了!
那么验证就是 \(\lfloor \log_{10} a \rfloor + 1 \geq n\) 则达到(超过),否则就没有达到。这样的验证是 \(\mathcal{O}(1)\) 的。
时间复杂度:\(\mathcal{O}(\log n)\).
实际得分:\(100pts\).
#pragma GCC optimize(2)
#include<bits/stdc++.h>
using namespace std;
inline int read(){char ch=getchar(); int f=1; while(ch<'0' || ch>'9') {if(ch=='-') f=-f; ch=getchar();}
int x=0; while(ch>='0' && ch<='9') x=(x<<3)+(x<<1)+ch-'0',ch=getchar(); return x*f;}
inline void write(int x) {
if(x<0) {putchar('-');write(-x);return;}
if(x<10) {putchar(char(x%10+'0'));return;}
write(x/10);putchar(char(x%10+'0'));
}
int main() {
int n=read()-1,l=1,r=1e9; //为了方便 , 先把 1 减掉
while(l<r) {
int mid=(l+r)>>1;
if(mid*log10(mid)<n) l=mid+1;
else r=mid; //二分答案
} printf("%d\n",r);
return 0;
}