不知道有没有用的科技。
$O(v)-O(1)\gcd$,其中 $v$ 是值域。
预处理
对于一个数 $n$,我们把它分解为 $(x,y,z)$,满足 $xyz=n,x\leq y\leq z$,且 $z\leq\sqrt n$ 或 $z$ 是质数。
下面证明其存在性:
若 $z>\sqrt n$ 且 $z$ 是合数,那么 $z$ 存在一个质因数 $\leq\sqrt n$,可以接着分解。
构造方法:
使用递归构造。
-
若 $n=1$,构造 $(1,1,1)$;
-
若 $n$ 是质数,构造 $(1,1,n)$;
-
若 $n$ 是合数,找到 $n$ 的最小质因子,$p$,找到 $m=n/p$ 的一个分解方法 $(x,y,z)$,那么 $n$ 的合法分解即为 $(px,y,z)$ 的升序排序。
证明:
易得 $x\leq\sqrt[3]m$。
-
若 $p\leq\sqrt[4]{n}$,则 $px\leq\sqrt[3]{np^2}\leq\sqrt n$。
-
否则 $p>\sqrt[4]n$
-
若 $x=1$,显然成立。
-
否则 $m$ 不是质数,可以得到 $x,y,z\ge p$,那么 $pxyz>\sqrt[4]{n}=n$,矛盾,不存在此情况。
-
询问
要求 $\gcd(a,b)$,分别枚举 $b$ 的三个因子,求出和 $a$ 的 $\gcd$,然后把 $a$ 除以这个 $\gcd$,三个因子的计算结果乘起来就是答案。
然后具体求法:
-
$x\leq\sqrt n$:预处理。
-
$x>\sqrt n,b\bmod x=0$:结果为 $x$。
-
$x>\sqrt n,b\bmod x\neq0$:结果为 $1$。
代码
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <vector>
#include <cstring>
using namespace std;
namespace solve
{
const int maxn = 1e6 + 10;
const int lim = 1000;
const int mod = 998244353;
int vis[maxn], pri[maxn], tot;
int div[maxn][3];
int table[lim + 1][lim + 1];
void init(int n = 1e6)
{
div[1][1] = div[1][2] = div[1][0] = 1;
for (int i = 2; i <= n; i++)
{
if (!vis[i])
{
pri[++tot] = i;
div[i][0] = 1, div[i][1] = 1, div[i][2] = i;
}
for (int j = 1; j <= tot && i * pri[j] <= n; j++)
{
int x = i * pri[j];
vis[x] = 1;
memcpy(div[x], div[i], sizeof(div[i]));
div[x][0] *= pri[j];
sort(div[x], div[x] + 3);
if (i % pri[j] == 0)
break;
}
}
for (int i = 0; i <= lim; i++)
for (int j = 0; j <= lim; j++)
table[i][j] = __gcd(i, j);
}
int get(int a, int b)
{
if (a <= lim && b <= lim)
return table[a][b];
int res = 1;
for (int i = 0; i < 3; i++)
{
int x;
if (div[b][i] <= lim)
x = table[div[b][i]][a % div[b][i]];
else if (a % div[b][i] == 0)
x = div[b][i];
else
x = 1;
res *= x;
a /= x;
}
return res;
}
int n;
int a[maxn], b[maxn];
void main()
{
init();
cin >> n;
for (int i = 1; i <= n; i++)
cin >> a[i];
for (int i = 1; i <= n; i++)
cin >> b[i];
for (int i = 1; i <= n; i++)
{
long long res = 0;
for (int j = 1, val = i; j <= n; j++, val = 1ll * val * i % mod)
res += 1ll * val * get(a[i], b[j]) % mod;
cout << res % mod << '\n';
}
}
}
int main()
{
ios::sync_with_stdio(false), cin.tie(0);
int T = 1;
// cin >> T;
while (T--)
solve::main();
}