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;
}

浙公网安备 33010602011771号