题目来源: XJTUOJ-1168 zxh的后宫管理系统

题目链接: https://oj.xjtuicpc.com/problem/1168

题面

一共 \(T\) 组数据.

现有一个未知的整数 \(k\), 满足 \(1\le k\le n\).

现在你被宣称 \(k\) 的值等于 \(x\), 但是你不知道真假. 你现在可以提交一个任意大的正整数 \(y\), 之后获得返回值 \(\gcd(k,y)\).

你需要寻找一个合适的 \(y\), 使得你可以通过返回值来查验 \(x\) 和 \(k\) 是否相等. 如果有很多满足条件的值, 选阿泽最小的那个. 如果没有合适的 \(y\), 输出 \(-1\).

由于 \(y\) 很大, 输出对 \(920011128\) 取模后的结果.

简要描述

给定 \(n, x\), 试给出一个最小的 \(y\), 使得 \(\forall 1\le a\le n\), 若 \(a\ne x\), 则 \(\gcd(a,y)\ne \gcd(x,y)\). 由于 \(y\) 很大, 输出对 \(920011128\) 取模后的结果.

数据范围

\[ 1\le T<10 \]

\[ 1\le k\le n\le10^7 \]

题解

答案为 \[ y=x\prod_{p\le n/x}p \] 证明见 2020 CCPC Wannafly 冬令营 Day1H 题解.

采用线性筛预处理 \([1,10^7]\) 中的所有素数. 若每次询问暴力计算素数乘积, 则复杂度为 \(O(Tn)\). 若采用前缀积, 则复杂度为 \(O(T+n)\).

代码实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 1e7 + 5;
const int p = 920011128;
vector<int> ps; // 所有素数
bool chk[maxn]; // 合数为true
ll psum[maxn];
void fillPrime(int rge)
{
for (int i = 2; i <= rge; i++)
{
if (!chk[i])
ps.push_back(i);
for (int j = 0; j < ps.size() && ps[j] <= rge / i; j++)
{
chk[i * ps[j]] = true;
if (i % ps[j] == 0)
break;
}
}
}
int main()
{
const int rge = 1e7 + 3;
fillPrime(rge);
psum[0] = psum[1] = 1;
for (int i = 2; i <= rge; ++i)
if (chk[i])
psum[i] = psum[i - 1];
else
psum[i] = psum[i - 1] * i % p;
int t;
cin >> t;
for (int tt = 0; tt < t; ++tt)
{
ll n, k;
cin >> n >> k;
cout << k * psum[n / k] % p << endl;
}
return 0;
}