前言
本人最开始考虑的是贪心,结果WA声一片。
问题就出在没有找反例。。。。。。
后来用DP做对了。
还发现结合了高精度算法。
思路
比较难的高精度。
容易想到贪心,不过这个贪心的策略大多都能找到反例。
我们可以考虑一下dp算法。
首先,我们用 f [ i ] [ j ] f[i][j] f[i][j] 表示前 i i i 个质数,此时 n n n 的值为 j j j 的最小的答案。
利用高精度dp不太现实。就算上FFT也会T掉。
把它变成乘积的形式之后,我们可以将其变成 log \log log 的形式就很容易转移了。
然后我们要干什么呢?
我们还得在做转移方程式的时候记录一下决策,最后做一遍高精。
值得一提的是 压位高精度时比如压 15 15 15 位那么最后输出的形式为:
printf("%015d",ans);
因为 m o d 1 e 15 \bmod 1e15 mod1e15 之后有效数位还有 15 15 15 个而并非 14 14 14 个.
Code
#include<bits/stdc++.h>
using namespace std;
int pri[18]={12,2,3,5,7,11,13,17,19,23,29,31,37};
int q[50005],top,c[18],an[18];
double hh[18],ans=1e6;
int n;
const int NN=1e7,N=7;
struct H{
int a[3000],len;
}a;
void outit(H a){
printf("%d",a.a[a.len]);
for(int i=a.len-1;i;i--){
for(int k=NN/10;a.a[i]<k;k/=10) cout<<0;
if(a.a[i]) cout<<a.a[i];
}
cout<<endl;
}
H chen(H a,H b){
H z;
z.len=a.len+b.len+2;
for(int i=1;i<=a.len;i++)
for(int j=1;j<=b.len;j++)z.a[i+j-1]+=(a.a[i]*b.a[j]);
for(int i=1;i<=z.len;i++)z.a[i+1]+=z.a[i]/NN,z.a[i]%=NN;
while(z.len>1&&!z.a[z.len])z.len--;
return z;
}
void cheng(int x){
for(int i=1;i<=a.len;i++)a.a[i]*=x;
for(int i=1;i<=a.len;i++){
a.a[i+1]+=a.a[i]/NN;
a.a[i]%=NN;
}
while(a.a[a.len+1]){
a.len++;a.a[a.len+1]+=a.a[a.len]/NN;a.a[a.len]%=NN;
}
}
void mk(){
for(int i=1;i<=pri[0];i++) hh[i]=log2(pri[i]);
for(int i=n;i;i--) if(n%i==0) q[++top]=i;
}
void Gets(double x){
ans=x;
for(int i=1;i<=12;i++)an[i]=c[i];
}
void dfs(int x,int now,int t,double temp){
if(ans<=temp)return;
if(now==1){Gets(temp);return;}
if(x>pri[0])return;
for(int i=t;i<=top;i++)
if(now%q[i]==0){
c[x]=q[i]-1;
dfs(x+1,now/q[i],i,temp+hh[x]*(q[i]-1));
c[x]=0;
}
}
int main()
{
cin>>n;
mk();
dfs(1,n,1,0);
a.a[1]=1;
a.len=1;
for(int i=1;i<=12;i++)
for(int j=1;j<=an[i];j++)cheng(pri[i]);
outit(a);
}