Codeforces 991
991 F
题意
给一个 \(\le 10^{10}\) 的正整数,使用'0'~'9','+','*','^'//乘方
字符表示这个数。求表示方法所形成的字符串长度最小的一种。
Examples
Input
2018
Output
2018
Input
1000000007
Output
10^9+7
Input
10000000000
Output
100^5
Input
2000000000
Output
2*10^9
解
首先,仅用'+','*'
不能减小长度。
其次,乘方的底数必然 \(\le \sqrt{n}\) 。
再次,所有的数最多只能表示为 \(a^b*c^d+e^f\) 的形式。
于是,brute force枚举所有情况即可。中间可以用一些小小的优化,如二分。
复杂度\(O(玄学)≈O(\sqrt{n}\log n)\)。
Code
#include<bits/stdc++.h>
#define INF 1050000000
using namespace std;
typedef long long D;
D n;
D len(D a){
if(!a)return 1;
D ret=0;
while(a)ret++,a/=10;
return ret;
}
struct data{
D a,b,c,d,e,f,val,l; //a^b*c^f+d^e
data():c(1),d(0),e(1),f(1){}
data(D _a,D _b,D _val):a(_a),b(_b),c(1),d(0),e(1),f(1),val(_val){}
bool operator <(const data& dat)const{
return val==dat.val?l<dat.l:val<dat.val;
}
void calc(){
l=len(a)+len(b)+len(c)+len(d)+len(e)+len(f)+5;
if(b==1)l-=2;
if(c==1)l-=2;
if(d==0)l-=2;
if(e==1)l-=2;
if(f==1)l-=2;
}
}a[1000000],b[1000000];
D cnt;
int main(){
cin>>n;
a[++cnt]=data(n,1,n);
a[cnt].calc();
b[cnt]=a[cnt];
for(D i=2;i*i<=n;i++){
for(D j=i,k=1;j<=n;j*=i,k++){
a[++cnt]=data(i,k,j);
a[cnt].c=n/a[cnt].val;
a[cnt].d=n-a[cnt].val*a[cnt].c;
a[cnt].calc();
b[cnt]=a[cnt];
}
}
sort(b+1,b+cnt+1);
for(D i=1;i<=min(cnt,10000ll);i++){
for(D j=1;j<=100;j++){
D l=1,r=cnt,mid,ans=-1;
while(l<=r){
mid=(l+r)>>1;
if(a[i].val*j+b[mid].val==n)ans=mid,r=mid-1;
else if(a[i].val*j+b[mid].val<n)l=mid+1;
else r=mid-1;
}
if(ans!=-1){
a[++cnt]=a[i];
a[cnt].c=j;
a[cnt].d=b[ans].a;
a[cnt].e=b[ans].b;
a[cnt].calc();
}
}
}
for(D i=1;i<=min(cnt,500000ll);i++){
D l=1,r=cnt,mid,ans=-1;
while(l<=r){
mid=(l+r)>>1;
if(a[i].val*b[mid].val<=n)ans=mid,l=mid+1;
else r=mid-1;
}
if(ans!=-1){
a[++cnt].a=a[i].a;
a[cnt].b=a[i].b;
a[cnt].c=b[ans].a;
a[cnt].f=b[ans].b;
a[cnt].d=n-a[i].val*b[ans].val;
a[cnt].calc();
}
}
int minn=INF,mini;
for(D i=1;i<=cnt;i++){
if(a[i].l<minn){
minn=a[i].l;
mini=i;
}
}
cout<<a[mini].a;
if(a[mini].b!=1)cout<<"^"<<a[mini].b;
if(a[mini].c!=1)cout<<"*"<<a[mini].c;
if(a[mini].f!=1)cout<<"^"<<a[mini].f;
if(a[mini].d!=0)cout<<"+"<<a[mini].d;
if(a[mini].e!=1)cout<<"^"<<a[mini].e;
return 0;
}