思路:
设 $f(x)$ 表示除 $x$ 本身之外,$x$ 的最大约数
既然要求 $L \sim R$ 中的每一个数 $x$ , $f(x)$ 的最大值(后文简写为 $ans$ ),那么就有了第一种算法:暴力枚举
但是你会发现只有 $30$ 分, $T$ 飞了(甚至有几个点 $RE$ 了我也不知道为啥)
#include<bits/stdc++.h>
#define int unsigned long long
using namespace std;
int check(int x){
for(int i=x-1;i>=2;i--){
if(x%i==0)return i;
}
}
int max(int x,int y){
if(x>y)return x;
else return y;
}
int l,r,maxx=0;
signed main(){
cin>>l>>r;
for(int i=l;i<=r;i++){
maxx=max(maxx,check(i));
}
cout<<maxx<<endl;
return 0;
}
那么我们就需要优化
先看测试数据:
$2 \leq L < R \leq 10^{18}$
因为 $L$ 到 $R$ 的区间包含 $L$ 和 $R$ ,由此可得:
$L$ 到 $R$ 的区间内至少包含两个连续整数
$\because$ 两个连续整数的奇偶性不一致
$\therefore$ 区间内必有一个偶数
$\therefore$ 当 $x$ 能被 $2$ 整除时, $f(x)=\frac{x}{2}$
又 $\because\frac{x+2}{2} \geq \frac{x}{2}$
$\therefore ans$ 的取值分两种情况:
- $R \bmod 2=0$ :$ans=\frac{R}{2}$
- $R \bmod 2=1$ :$ans=\frac{R-1}{2}$
那么代码就出来了:
#include<bits/stdc++.h>
#define int unsigned long long
using namespace std;
inline int read(){//快读优化
int x=0,f=1;
char c=getchar();
for(;c<'0'||c>'9';c=getchar())
if(c=='-')f=-1;
for(;c<='9'&&c>='0';c=getchar())
x=(x<<3)+(x<<1)+c-'0';
return x*f;
}
inline void out(int x){//输出优化
if(x>9)out(x/10);
putchar(x%10+'0');
}
int l,r;
signed main(){
l=read(),r=read(); //输入区间
out(r>>1);//输出 r/2 的值(因为 c++ 在整数除法中会自动向下取整,所以只需要输出 r/2 就可以了)
return 0;//结束程序
}