原题链接
题目描述
这是一道非常水的题目:
大概意思是:给你两个数, m ( 1 ≤ m ≤ 50 ) m(1\le m\le 50) m(1≤m≤50) 和 n ( 1 ≤ n ≤ 1 0 10000 ) n(1\le n\le 10^{10000}) n(1≤n≤1010000),求 n m \sqrt[m]{n} mn。
解题思路
这题,一看就是高精度。高精度的开根,如果上网搜,会搜索出各种玄学解法,但是由于太玄学,大部分人都无法理解,我们可以采用一种非常朴素的写法:二分。粗略地算了一下时间复杂度,但如果使用暴力,那么时间复杂度将会达到 O ( l o g 2 n ) O(log_{2}n) O(log2n),很好,愉快超时。为了解决这个问题,我们需要使用一点数学优化: ⌊ l o g 10 ( ⌊ l o g 10 n ⌋ / m ) ⌋ − 1 ≤ ⌊ l o g 10 n m ⌋ ≤ ⌊ l o g 10 ( ⌊ l o g 10 n ⌋ / m ) ⌋ + 1 \lfloor log_{10}(\lfloor log_{10}n\rfloor/m)\rfloor-1 \le \lfloor log_{10}\sqrt[m]{n}\rfloor \le \lfloor log_{10}(\lfloor log_{10}n\rfloor/m)\rfloor+1 ⌊log10(⌊log10n⌋/m)⌋−1≤⌊log10mn⌋≤⌊log10(⌊log10n⌋/m)⌋+1(简单来说,就是答案的位数是根号下数的位数除以开的次方数 ± 1 \pm 1 ±1),也就是说如: ⌊ l o g 10 ( ⌊ l o g 10 100000000 ⌋ / 2 ) ⌋ − 1 ≤ ⌊ l o g 10 100000000 2 ⌋ ≤ ⌊ l o g 10 ( ⌊ l o g 10 100000000 ⌋ / 2 ) ⌋ + 1 \lfloor log_{10}(\lfloor log_{10}100000000\rfloor/2)\rfloor-1 \le \lfloor log_{10}\sqrt[2]{100000000}\rfloor \le \lfloor log_{10}(\lfloor log_{10}100000000\rfloor/2)\rfloor+1 ⌊log10(⌊log10100000000⌋/2)⌋−1≤⌊log102100000000⌋≤⌊log10(⌊log10100000000⌋/2)⌋+1(答案是5位,在 ⌊ 9 / 2 ⌋ − 1 \lfloor 9/2\rfloor-1 ⌊9/2⌋−1到 ⌊ 9 / 2 ⌋ + 1 \lfloor 9/2\rfloor+1 ⌊9/2⌋+1之间)。如此,可以将时间复杂度降低至 O ( l o g 2 1000 ) O(log_21000) O(log21000)。结果,一提交:
妙啊!还是超时,继续优化。无能为力之下,只能使用压位高精。
压位高精:
c++里的高精通常都是这样的:
a:1 | 2 | 3 | 4 |
b:1 | 2 | 3 | 4 |
但是,既占空间,又占时间。我们发现,就算是使用 i n t int int,也可以,存下 0 ∼ 2147483647 0\sim 2147483647 0∼2147483647,所以如果说这么存:
a:1234
b:1234
就OK了(时间复杂度将会降低至原来的 1 压 位 位 数 2 \frac 1 {压位位数^2} 压位位数21)。
终于,历经千辛万苦后:
代码实现
#include<iostream>
#include<algorithm>
#include<cmath>
#include<map>
#include<ctime>
#include<fstream>
#include<queue>
#include<vector>
#include<stack>
#include<string>
#include<cstring>
#include<cstdio>
#include<set>
using namespace std;
struct node{
unsigned long long h_int[5000],lenth;
};
struct node2{
node ds,ys;
};
string a;
long long n;
node jia(node jia1,node jia2)
{
node ans;
unsigned long long jw=0,t;
ans.lenth=max(jia1.lenth,jia2.lenth)+1;
for(long long i=1;i<=4999;++i){
t=jia1.h_int[i]+jia2.h_int[i]+jw;
jw=t/100000000ll;
ans.h_int[i]=t%100000000ll;
}
if(ans.h_int[ans.lenth]==0)
ans.lenth--;
return ans;
}
node jian(node jian1,node jian2)
{
node ans;
unsigned long long t,jw=0;
for(long long i=1;i<=4999;i++){
if(jian1.h_int[i]-jw>=jian2.h_int[i]){
ans.h_int[i]=jian1.h_int[i]-jian2.h_int[i]-jw;
jw=0;
}
else{
ans.h_int[i]=100000000ll+jian1.h_int[i]-jian2.h_int[i]-jw;
jw=1;
}
}
ans.lenth=2500;
while(ans.h_int[ans.lenth]==0&&ans.lenth>0)
ans.lenth--;
return ans;
}
node cheng(node s1,node s2)
{
node ans;
memset(ans.h_int,0,sizeof(ans.h_int));
ans.lenth=s1.lenth+s2.lenth;
unsigned long long t,jw=0;
for(long long i=1;i<=s1.lenth;++i)
for(long long j=1;j<=s2.lenth;++j){
t=s1.h_int[i]*s2.h_int[j]+jw;
ans.h_int[i+j-1]+=t;
}
for(int i=1;i<=ans.lenth;i++){
ans.h_int[i+1]+=ans.h_int[i]/100000000ll;
ans.h_int[i]%=100000000ll;
}
if(ans.h_int[ans.lenth]==0)
ans.lenth--;
return ans;
}
bool q_bigger_h(node q,node h)
{
if(q.lenth!=h.lenth) return q.lenth>h.lenth;
for(int i=q.lenth;i>0;i--)
if(q.h_int[i]!=h.h_int[i])
return q.h_int[i]>h.h_int[i];
return false;
}
node chu(node bcs)
{
node ans;
ans=bcs;
for(int i=ans.lenth;i>=2;i--){
ans.h_int[i-1]+=(ans.h_int[i]%2)*100000000ll;
ans.h_int[i]/=2;
}
ans.h_int[1]/=2;
if(ans.h_int[ans.lenth]==0)
ans.lenth--;
return ans;
}
node cifang(node d,unsigned long long zs)
{
node ans,s=d;
ans.lenth=1;
ans.h_int[1]=1;
while(zs!=0){
if(zs%2==1)
ans=cheng(ans,s);
s=cheng(s,s);
zs=zs/2;
}
return ans;
}
long long log_10(unsigned long long n){
long long ans=0;
while(n!=0){
n/=10;
ans++;
}
return ans;
}
unsigned long long to_n(string a)
{
unsigned long long value=0;
for(long long i=0;i<a.size();i++)
value=value*10+a[i]-'0';
return value;
}
string ycl_l(long long l)
{
string value="1";
for(long long i=2;i<=l;i++)
value+="0";
return value;
}
string ycl_r(long long l)
{
string value="";
for(long long i=1;i<=l;i++)
value+="9";
return value;
}
bool e(node q,node h)
{
if(q.lenth!=h.lenth)
return false;
for(int i=1;i<5000;i++)
if(q.h_int[i]!=h.h_int[i])
return false;
return true;
}
int main()
{
ios::sync_with_stdio(false);
node jia_1;
jia_1.lenth=1;
jia_1.h_int[1]=1;
cin>>n;
cin>>a;
if(n==1){
cout<<a;
return 0;
}
if(a=="1"||a=="0"){
cout<<a;
return 0;
}
node a_t;
string t="";
a_t.lenth=0;
int len=a.size()-1,n_len=a.size();
memset(a_t.h_int,0,sizeof(a_t.h_int));
while(len>6){
t=a.substr(len-7,8);
a_t.h_int[++a_t.lenth]=to_n(t);
len-=8;
}
if(len>=0){
t=a.substr(0,len+1);
a_t.h_int[++a_t.lenth]=to_n(t);
}
string l="",r="";
if(a.size()/n-1<=0)
l="0";
else
l=ycl_l(a.size()/n-1);
if(a.size()/n+1>a.size())
r=a;
else
r=ycl_r(a.size()/n+1);
node l_t,r_t;
len=l.size()-1,n_len=l.size();
memset(l_t.h_int,0,sizeof(l_t.h_int));
l_t.lenth=0;
while(len>6){
t=l.substr(len-7,8);
l_t.h_int[++l_t.lenth]=to_n(t);
len-=8;
}
if(len>=0){
t=l.substr(0,len+1);
l_t.h_int[++l_t.lenth]=to_n(t);
}
len=r.size()-1,n_len=r.size();
memset(r_t.h_int,0,sizeof(r_t.h_int));
r_t.lenth=0;
while(len>6){
t=r.substr(len-7,8);
r_t.h_int[++r_t.lenth]=to_n(t);
len-=8;
}
if(len>=0){
t=r.substr(0,len+1);
r_t.h_int[++r_t.lenth]=to_n(t);
}
node mid,mid_n;
do{
mid=chu(jia(l_t,r_t));
mid=jia(mid,jia_1);
mid_n=cifang(mid,n);
if(e(mid_n,a_t)){
cout<<mid.h_int[mid.lenth];
for(int i=mid.lenth-1;i>0;i--){
if(mid.h_int[i]!=0)
for(long long j=1;j<=8-log_10(mid.h_int[i]);j++)
cout<<0;
else
cout<<"0000000";
cout<<mid.h_int[i];
}
return 0;
}
if(q_bigger_h(mid_n,a_t))
r_t=jian(mid,jia_1);
else
l_t=mid;
}
while(q_bigger_h(r_t,l_t));
cout<<l_t.h_int[mid.lenth];
for(int i=l_t.lenth-1;i>0;i--){
if(l_t.h_int[i]!=0)
for(long long j=1;j<=8-log_10(l_t.h_int[i]);j++)
cout<<0;
else
cout<<"0000000";
cout<<l_t.h_int[i];
}
return 0;
}
样例1
输入
3
1000000000
输出
1000
样例2
输入
2
100000000020000000001
输出
10000000001
样例3
输入
50
1
输出
1