题目分析
由于 ,所以除了 外,其他数都是9位,所以如果我们要更换表示法,这个新表示法应该要小于等于8位。而 的最简表示法显然也不会超过8位。
考虑表示法里会有几个加号。发现把一个简单数字(即不带乘号和幂号的项)表示为一个简单数字加一个简单数字的形式,位数一定不会减少,因此加号串联的几个项中,最多有一个项是简单数字,又因为表示法不能超过8位,所以最多用2个加号,并且这三项的长度分别是3,3,1。又因为9^9+9^9+9=774840987
并没有减少表示法长度,所以加号最多有一个。
接着发现,一个
位的简单数字
和一个
位的简单数字
相乘,结果的位数不会大于
。所以一个项也不能写成
的形式,因而如果要将
更换表示法,其中一定有一个幂次表达(即表示法中一定存在a^b
的形式。)
那么我们可以把所有能够被幂次表达,且小于
的数及它的最简幂次表达用一个map存一下,这个总共是根号级别的。然后取每一个幂次表达,将其写成C*a^b+D
的形式,其中C和D是简单数字或被幂次表达的项,并且
且
这个做法看起来很正确,但是这时候有Lcy发问了,凭什么 和 就是这样取的呢?能不能把 稍微减小一点,使得 位数减小,并且 位数不变,使得表示法更优呢?
既然
位数可以减小,说明至少有两位。a和b至少一位,D至少一位,加上三个符号,正好是8位。由于C减小1后,D要变成
,应该还是1位,所以
一定是一个一位数。我们发现会发生Lcy提问条件的数
,都是两位数,根本不需要写成C*a^b+D
的形式,所以我们不用考虑这个问题,该做法正确。
代码
注意要用C++17提交,C++11太慢了QAQ
#pragma G++ optimize (2)
#include<bits/stdc++.h>
using namespace std;
#define RI register int
typedef long long LL;
LL n,sqn;string ans;
map<LL,string> mp;
int main()
{
cin>>n;
sqn=sqrt(n);
for(LL i=2;i<=sqn;++i) {
string ii=to_string(i);
if(!mp.count(i)||mp[i].length()>ii.length()) mp[i]=ii;
for(LL j=i*i,k=2;j<=n;j*=i,++k) {
string kl=ii+"^"+to_string(k);
if(!mp.count(j)||mp[j].length()>kl.length()) mp[j]=kl;
}
}
ans=to_string(n);
for(map<LL,string>::iterator it=mp.begin();it!=mp.end();++it) {
string kl;LL x=(*it).first;
if(n/x!=1) {
string y=to_string(n/x);
if(mp.count(n/x)&&mp[n/x].length()<y.length()) kl+=mp[n/x]+"*";
else kl+=y+"*";
}
kl+=(*it).second;
if(n%x!=0) {
string y=to_string(n%x);
if(mp.count(n%x)&&mp[n%x].length()<y.length()) kl+="+"+mp[n%x];
else kl+="+"+y;
}
if(kl.length()<ans.length()) ans=kl;
}
cout<<ans;
return 0;
}