D 题非常好爆搜练习题,需要不少观察,质量严格大于 E 一个思路比较一眼代码有点史的背包。
首先考虑求出 的最大值。注意到由于这个
包含的质数种类数肯定不超过
所以
也不会太大。赛时如果想保险一点二分上界取
然后暴力判断就好。但事实上上界取
就足够了。
得到了 后我们肯定需要
个位置达到
。现在还剩
个位置。考虑在剩下的位置再放上一些数使得
继续变大。
我们观察注意到 。证明是容易的,由于
是二分得出来的所以就有
。综上,剩下的位置放的数的质因子不会超过
,因此使得
变大但不大于
的方案数也不会多。直接从质因子的角度爆搜是可行的。
但是现在还有一个问题是当 与
非常接近时
即剩余位置非常少,放的数不能多。所以确定了这
个数的质因子及其幂次后还得压缩一下。这时候一个贪心是将质因子的若干次方根据从大到小排序然后能乘在一起不超过
就直接相乘压缩,否则再开一个位置放数,使得耗费位置尽可能少。最后判断耗费位置是否超过
,没超就贡献到答案。
code
#include <bits/stdc++.h>
#define ED cerr<<endl;
#define TS cerr<<"I AK IOI"<<endl;
#define cr(x) cerr<<x<<endl;
#define cr2(x,y) cerr<<x<<" "<<y<<endl;
#define cr3(x,y,z) cerr<<x<<" "<<y<<" "<<z<<endl;
#define cr4(x,y,z,w) cerr<<x<<" "<<y<<" "<<z<<" "<<w<<endl;
#define pii pair<int,int>
#define epb emplace_back
#define pb push_back
#define mk make_pair
#define fi first
#define se second
#define int long long
using namespace std;
const int N=1e3+5,INF=2e9,mod=1e9+7;
int t,n,x,y,R,ans;
int primes[N],cnt=0;
bool st[N];
void get(int n) {
for(int i=2;i<=n;++i) {
if(!st[i]) {
primes[++cnt]=i;
}
for(int j=1;j<=cnt&&primes[j]<=n/i;++j) {
st[primes[j]*i]=true;
if(i%primes[j]==0) break;
}
}
}
int gcd(int x,int y) {
return !y?x:gcd(y,x%y);
}
int lcm(int x,int y) {
return x/gcd(x,y)*y;
}
bool check(int mid) {
int nw=1;
for(int i=1;i<=mid;++i) {
nw=lcm(nw,i);
if(nw>y) return false;
}
return true;
}
vector<int> S;
void dfs(int dep,int res) {
if(dep>cnt||primes[dep]>R) {
vector<int> s=S;
sort(s.begin(),s.end(),greater<int>());
int cnt=1,nw=1;
for(auto it:s) {
if(nw>x/it) ++cnt,nw=it;
else nw*=it;
}
if(R+cnt<=n) ans=max(ans,res);
return;
}
int mul=1,val=primes[dep];
while(1) {
mul*=val;
if(res%mul==0) continue;
int to=lcm(res,mul);
if(to>y||mul>x) break;
else {
S.epb(mul);
dfs(dep+1,to);
S.pop_back();
}
}
dfs(dep+1,res);
}
void sol() {
scanf("%lld%lld%lld",&n,&x,&y);
int l=1,r=min({x,n,500ll});R=0;
while(l<=r) {
int mid=l+r>>1;
if(check(mid)) R=mid,l=mid+1;
else r=mid-1;
}
ans=1;
for(int i=1;i<=R;++i) {
ans=lcm(ans,i);
}
if(R==n) printf("%lld\n",ans);
else {
dfs(1,ans);
printf("%lld\n",ans);
}
}
signed main()
{
get(1000);
scanf("%lld",&t);
while(t--) {
sol();
}
return 0;
}