XJTUOJ #1168 zxh的后宫管理系统
题目描述
大家都认为 Sheauhaw 有一个庞大的后宫, 于是后宫管理系统应运而生. 该后宫管理系统为了满足 Sheauhaw 的特殊需求, 众生平等, 甚至可以录入任何实体的信息! 下面是该系统的运营方式:
后宫管理系统中一共存储了\(n\)个实体的信息, 每个实体都有一个从\(1\)到\(n\)的编号. 你可以向后宫管理员 Zeondik 查询某个实体的编号, 管理系统会返回一个编号\(x\).
但是, 由于系统不稳定, 你暂时不能确定这个\(x\)的正确性, 假设真实编号是\(k\). 好在你可以向 Sheauhaw 核实该返回值, 但是 Sheauhaw 比较神秘, 不会直接告诉你对或者错, 也不会直接告诉你编号, 而是用一种奇怪的方式核实: Sheauhaw 可以让你呈上一个整数\(y\), 然后大发慈悲地告诉你\(gcd(k,y)\).
聪明无比的你一定有一个合适的\(y\)的选择, 将这个数字告诉 Sheauhaw 可以准确地判断\(x\)的正确性. 然而, Sheauhaw 喜欢小的东西, 管理员 Zeondik 要求你在所有合适的\(y\)中挑选一个最小的\(y\)告诉 Sheauhaw, 并检查你的\(y\)是否最小. 但\(y\)可能很大, 你只需要输出\(y\)对\(920,011,128\)取模的数值即可: 如果你的输出\(y'\equiv y_m (\) \(mod\) \(920,011,128)\), Zeondik 就会让你通过.
如果没有合适的\(y\), 输出\(-1\).
输入格式
第一行一个整数\(T\), 表示查询次数.
每组数据输入一行, 每行两个整数\(n,x\), 表示编号范围和系统输出.
输出格式
每组输出输出一行, 一行一个整数, 表示\(y\)对\(920,011,128\)取模后的值. 如果没有合适的选择, 输出\(-1\).
数据范围
\(1\leq T<10\)
\(1\leq k\leq n\leq 10^7\)
思路
枚举y显然不太好,我们换个思路,枚举gcd的值g,并判断哪些g对我们更有用。
显然g必须整除x,那么如果g是x的真因子,那么g本身这个数就满足\(gcd(g,x)=g\),并不是独一无二的。
所以我们断定,合理的y必然满足\(gcd(x,y)=x\),也就是说y是x的倍数。
那么可能扰乱我们的只剩1~n中x的倍数了。
那么对于任意k(k>1) 我们要保证\(gcd(y,kx)\neq x\),相当于\(gcd(\frac{y}{x},k)\neq 1\),而k的范围是\((1,\frac{n}{x}]\),所以 \(\frac{y}{x}\) 就是\([1,\frac{n}{x}]\)之间所有素数的乘积。
总结一下,令\(f(x)\)表示\([1,n]\)内所有素数乘积,则\(ans(n,x)=x*f(\frac{n}{x})\)。
代码
#include <cstdio>
#include <cstdlib>
#define mod 920011128
#include <algorithm>
#define maxn (int)(1e7 + 1)
#define ll long long
using namespace std;
ll f[maxn], p[maxn];
int book[maxn], cnt = 0, t[11][2];
int main() {
int T, i, j, n = 0;
ll ans;
scanf("%d", &T);
for (i = 1; i <= T; i++) {
scanf("%d%d", &t[i][0], &t[i][1]);
n = max(n, t[i][0]);
}
book[1] = 1;
f[0] = f[1] = 1;
for (i = 2; i <= n; i++) {
if (!book[i]) {
p[++cnt] = i;
}
for (j = 1; j <= cnt && i * p[j] <= n; j++) {
book[i * p[j]] = 1;
if (!(i % p[j]))
break;
}
}
for (i = 2; i <= n; i++) {
if (book[i])
f[i] = f[i - 1];
else
f[i] = f[i - 1] * i % mod;
}
for (i = 1; i <= T; i++) {
ans = t[i][1] * f[t[i][0] / t[i][1]] % mod;
printf("%lld\n", ans);
}
return 0;
}