一.闲话
哎,之前开C的时候,发现有点计算几何的味道,就打算放放,开D,结果发现D是数论,于是就决定搞出来了。然后一直Wa。。。debug了几个小错误后,实在没发现错了。。。结果后面rejudge就过了???/xk
二.题解
首先,这题几个结论:
1.我们不会选两个相同的数(除了用1来补满和以外)
这个证明就不说了,很naive
2.我们放的数一定是放的一个质数的k次方。
为啥呢?
我们分析下,假如我们放了一个数那么,其实,等价于我们分别放了两个数
(甚至我们单独放这两个数的答案可能还要大点。。。),然后,由于
恒成立,所以贪心来看,我们用更小的代价,换到了更大的收益,那么要获得最大收益肯定是用的这个策略。所以结论成立。
3.如果我们选了,那么我们必然选了
证明也很简单,如果我们有一个没选,那么,我们将k次换成那个后,贡献不变,代价减小了。所以要选的话必然是连续选的。
4.
和上面的分析方式类似,若,那么我们
取
个
取
个,与现在的取法的答案是一样的,但是这种取法的代价明显小于现在的取法。
有了上述几个结论后,做法就很显然了,类比于做求1-n中公约数最多的数那个做法,我们dfs枚举每个质数取几个就行了。每次将当前答案取最大即可。
那么,如何计算代价呢?
一开始肯定是1(空集的一个)。
那么,假如加入前的答案为x,我们加入了一组后,我们发现,对于原来的每个lcm,都一定与现在的这
个数互质,那么对于每个lcm,就会多出
个不同的分支(分别加入这几个中其中一个)。
所以现在的答案就变成了那么,我们如果加入多个
的次方怎么办?其实还是等价于我们只加入最大的那个而已。(因为有空集,所以答案完备)
所以代码就很好打了。
那么,又来了一个问题。
我们的答案是要取模的,取模后大小关系会变化啊?怎么办呢?有几种办法,我直接说下我naive的做法吧。我直接上一个高精,然后最后输出答案的时候取模即可。
但是,打普通高精会TLE,那么,压个位就好了。(最好多压几位,跑得快点)
代码:
#pragma GCC optimize(3,"inline","Ofast")
#include<bits/stdc++.h>
using namespace std;
#define int long long
const int N=1e5+1,mod=1e9+7,inf=2e9;
const long long T=1e15;
int a[N];
int zhi[N],e;bool f[N];int n;
int sav[N];
struct node{
long long a[6];
}ans;
inline node max(node x,node y){
for(int i=5;~i;--i){
if(x.a[i]!=y.a[i]){
return x.a[i]>y.a[i]?x:y;
}
}
return x;
}
inline void sai(){
for(int i=2;i<N;++i){
if(!f[i]){
zhi[++e]=i;
}
for(int j=1;j<=e;++j){
if(i*zhi[j]>=N)break;
f[i*zhi[j]]=1;
if(i%zhi[j]==0)break;
}
}
}
inline node operator*(node x,int y){
for(int i=0;i<=5;++i)x.a[i]*=y;
for(int i=0;i<5;++i)x.a[i+1]+=x.a[i]/T,x.a[i]%=T;
return x;
}
inline int operator%(node x,int y){
__int128 now=0;
for(int i=5;~i;--i){
now=(now*T)%y;now=(now+x.a[i])%y;
}
int fow=now;
return fow;
}
inline void dfs(int now,int sum,int x,node res){//枚举其次即可
ans=max(ans,res);
int lon=1,tot=0;
for(int i=1;i<=x;++i){
lon*=zhi[now];tot+=lon;
if(sum+tot>n)break;
sav[now]=i;
//将zhi[now]^1...zhi[now]^i添加进去
//每个都和之前的所有互质,那么,单独来看,即添加了res*i个
node tp=res*(i+1);
dfs(now+1,sum+tot,i,tp);
}
}
node st;
signed main(){
sai();
scanf("%lld",&n);
if(n==1){
puts("1");
return 0;
}
//添加的必然为pi^k
st.a[0]=1;
dfs(1,0,inf,st);
int ant=ans%mod;
printf("%lld",ant);
system("pause");
return 0;
} 
京公网安备 11010502036488号