MX 暑假集训 8.4

【中文CC字幕】【MORE MORE JUMP! × 巡音ルカ】ももいろの鍵(桃色钥匙)【2DMV/『世界计划 多彩舞台』主题原创曲】

数学专题,不会数论,等我重新学一遍数论再写 T-T。

[POI 2014] PAN-Solar Panels

题意

\(q\) 次询问,每次询问给定 \(a,b,c,d\),求从 \([a,b]\) 中选出一个数 \(x\)\([c,d]\) 中选出一个数 \(y\)\(\gcd(x,y)\) 的最大值是多少。

\(1\le q\le 2000,1\le a,b,c,d\le 10^9\)

solution

考虑一个数 \(g\),它的倍数在 \((l,r]\) 内出现当且仅当 \(\left\lfloor \frac{l}{g}\right\rfloor<\left\lfloor \frac{r}{g}\right\rfloor\),因为这个式子的意义是 \(r\) 以内 \(g\) 倍数个数超过 \(l\) 以内 \(g\) 倍数个数。

题目要求找到最大的 \(g\),满足 \(\left\lfloor \frac{a-1}{g}\right\rfloor<\left\lfloor \frac{b}{g}\right\rfloor\land \left\lfloor \frac{c-1}{g}\right\rfloor<\left\lfloor \frac{d}{g}\right\rfloor\)

直接枚举 \(g\) 复杂度过高,所以考虑整除分块,枚举 \(\left\lfloor \frac{b}{g}\right\rfloor\)\(\left\lfloor \frac{d}{g}\right\rfloor\),以枚举 \(\left\lfloor \frac{b}{g}\right\rfloor\) 为例,令这个值为 \(k\),那么找到最大的区间 \([l,r]\) 满足 \(g\in [l,r]\)\(\left\lfloor \frac{b}{g}\right\rfloor=k\),那么当 \(g=r\) 时一定不劣,因为此时 \(k\) 不变且 \(\left\lfloor \frac{a-1}{g}\right\rfloor\) 最小,同时答案 \(g\) 尽可能大。

对于每个块 \([l,r]\) 判断右端点 \(r\) 是否满足上述条件即可,由整除分块分析单组数据复杂度为 \(O(\sqrt V)\)

时间复杂度 \(O(n\sqrt V)\)

Code
#include<cstdio>
#include<algorithm>
using namespace std;
#define ll long long
#define qwq Ff472130
#define f(i,l,r) for (int i=l;i<=r;i++)
#define F(i,l,r) for (int i=l;i>=r;i--)
constexpr int N=2e5+10;
constexpr int inf=1e9+10;

inline void read(int &x) {
	x=0;
	char ch=getchar();
	while (ch<48) ch=getchar(); 
	while (ch>=48) x=(x<<3)+(x<<1)+(ch^48),ch=getchar();
}

inline void solve() {
	int a,b,c,d,ret=0;
	read(a);read(b);read(c);read(d);
	for (int L=1,R=1,len=min(b,d);L<=len;L=R+1) {
		int k1=b/L,k2=d/L;
		R=min(b/k1,d/k2);
		if (R*k1>=a&&R*k2>=c) ret=R;
	}
	printf("%d\n",ret);
}

int main() {
	int T;
	read(T);
	while (T--) solve();
	return 0;
}
posted @ 2026-08-04 15:34  Ff472130  阅读(11)  评论(2)    收藏  举报