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;
}
posted @ 2020-10-13 11:49  文艺平衡树  阅读(217)  评论(0编辑  收藏  举报