Description
详见OJ
Solution
感觉这题是最神仙的。。。
考场\(AC\)的人说自己是暴力枚举转移方程而得到了一个正确的转移式。
对于数据中的\(x\),我们发现分解质因数后,每个质因数的指数最大是\(2\)。
当指数为\(1\)的时候,很容易得出答案乘以\(n!\)(因为每列每行都只能有一个这个质数)
当指数为\(2\)的时候,那人通过暴枚得出\(f[i]=i*i*f[i-1]+i*(i-1)*(i-1)/2*f[i-2]\),答案乘以\(f[n]\)。
最后再乘以\(2^{(n-1)*(n-1)}\)即可。
Code
#include <cstdio>
#define N 5000000
#define ll long long
#define mo 998244353
#define mem(x, a) memset(x, a, sizeof x)
#define fo(x, a, b) for (int x = a; x <= b; x++)
#define fd(x, a, b) for (int x = a; x >= b; x--)
using namespace std;
int T, n, cs[31][2], tot = 0;
ll x, f[N + 10], jc[N + 10], tot1 = 0, tot2 = 0;
inline int read()
{
int x = 0; char c = getchar();
while (c < '0' || c > '9') c = getchar();
while (c >= '0' && c <= '9') x = (x << 1) + (x << 3) + (c ^ 48), c = getchar();
return x;
}
ll ksm(ll x, int y)
{
ll s = 1;
while (y)
{
if (y & 1) s = s * x % mo;
x = x * x % mo; y >>= 1;
}
return s;
}
int main()
{
freopen("pj.in", "r", stdin);
freopen("pj.out", "w", stdout);
scanf("%lld", &x);
fo(i, 2, 3000)
if (x % i == 0)
{
// cs[++tot][0] = i;
tot = 0;
while (x % i == 0)
x /= i, tot++;
if (tot == 1) tot1++;
else tot2++;
}
if (x > 1) tot1++;
f[1] = 1, f[2] = 3; jc[1] = 1, jc[2] = 2;
for (ll i = 3; i <= N; i++)
{
f[i] = (i * i % mo * f[i - 1] % mo - i * (i - 1) / 2 % mo * (i - 1) % mo * f[i - 2] % mo + mo) % mo;
jc[i] = jc[i - 1] * i % mo;
}
T = read();
while (T--)
{
n = read();
printf("%d\n", ksm(jc[n], tot1) * ksm(f[n], tot2) % mo * ksm(2, (ll)(n - 1) * (n - 1) % (mo - 1)) % mo);
}
return 0;
}