http://main.edu.pl/en/archive/oi/21/pan
给定 a,b,c,d ,要找出点对 (i,j) , a≤i≤b,c≤j≤d ,使得 gcd(i,j) 最大,求最大的这个 gcd(i,j)
不妨考虑枚举 t=gcd(i,j) ,若在 a≤i≤b,c≤j≤d 的限制下存在 gcd(i,j)=t ,当且仅当 [bt]>[at],[dt]>[ct] 。
但是直接暴力枚举 gcd(i,j) 还是太慢,可以发现 [bt],[at],[dt],[ct] 各自的不同的值都只有根号数量个。那我们可以对 t=gcd(i,j) 进行分块,每个块里的所有的 t 求出的 [bt],[at],[dt],[ct] 的值都是一样的,并用每个块里最后一个 t 更新答案即可。
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <algorithm>
using namespace std;
int main()
{
int a,b,c,d,T;
scanf("%d",&T);
while(T--)
{
int ans=0;
int last;
scanf("%d%d%d%d",&a,&b,&c,&d);
for(int i=1;i<=b&&i<=d;i=last+1)
{
last=min(b/(b/i),d/(d/i));
if(b/last>(a-1)/last&&d/last>(c-1)/last)
ans=max(ans,last);
}
printf("%d\n",ans);
}
return 0;
}