题目描述
整除符号为 ∣ | ∣, d ∣ n d|n d∣n 在计算机语言中可被描述为 n % d = = 0 n\%d == 0 n%d==0。
现有一算式 n ∣ x m − x n|x^m-x n∣xm−x,给定 n n n, m m m,求 [ 1 , n ] [1, n] [1,n] 以内 x x x 解的个数。
解可能很大,输出取模 998244353 998244353 998244353。
输入输出格式
输入格式
其中 n n n 的给定方式是由 c c c 个不超过 t t t 的质数的乘积给出的, c c c 和 t t t 的
范围会在数据范围中给出。
第一行一个 i d id id 表示这个数据点的标号。
多组数据,其中第二行一个整数 T T T 表示数据组数。
对于每一组数据:
第一行两个整数 c c c 和 m m m。
第二行 c c c 个整数,这些整数都是质数,且两两不同,他们的乘积即为 n n n。
由于你可以通过输入求出 t t t,输入不再给出。
输出格式
对于每组数据输出一行,表示解的个数。
输入输出样例
输入样例#1:
0
1
2 3
2 3
输出样例#1:
6
解题分析
考虑我们每个 x m ≡ x ( m o d p i ) x^m\equiv x(mod\ p_i) xm≡x(mod pi)的解, 因为给出质数互不相等,两两都能合并成一个新的答案(类似 C R T CRT CRT的操作), 所以我们算出每个质数的解再乘起来就行了。
然而暴力快速幂似乎会 T L E TLE TLE?我们线性筛 x m x^m xm即可。
代码如下:
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cctype>
#include <algorithm>
#include <cmath>
#define R register
#define IN inline
#define W while
#define gc getchar()
#define MOD 998244353
#define ll long long
#define MX 20050
template <class T>
IN void in(T &x)
{
x = 0; R char c = gc;
for (; !isdigit(c); c = gc);
for (; isdigit(c); c = gc)
x = (x << 1) + (x << 3) + c - 48;
}
int pri[MX], pw[MX], pcnt;
bool npr[MX];
IN int fpow(R int base, R int tim, R int mod)
{
R int ret = 1;
W (tim)
{
if(tim & 1) ret = 1ll * ret * base % mod;
base = 1ll * base * base % mod, tim >>= 1;
}
return ret;
}
IN void get_pri()//先筛出质数, 降低常数
{
for (R int i = 2; i <= 10000; ++i)
{
if(!npr[i]) pri[++pcnt] = i;
for (R int j = 1; j <= pcnt; ++j)
{
if(pri[j] * i > 10000) break;
npr[pri[j] * i] = true;
if(!(i % pri[j])) break;
}
}
}
IN int get(R int tm, R int pr)//筛x^m
{
R int i, j;
pw[1] = 1, pw[pr] = 0; R int tar;
for (i = 2; i < pr; ++i)
{
if(!npr[i]) pw[i] = fpow(i, tm, pr);
for (j = 1; pri[j] <= i; ++j)
{
tar = pri[j] * i;
if(tar > pr) break;
pw[tar] = pw[pri[j]] * pw[i] % pr;
if(!(i % pri[j])) break;
}
}
int tot = 1;
for (i = 1; i < pr; ++i)
if(pw[i] == i) ++tot;
return tot;
}
IN int solve()
{
R int res = 1, pr, ct, tm, i;
in(ct), in(tm);
for (i = 1; i <= ct; ++i)
in(pr), res = 1ll * res * get(tm, pr) % MOD;
return res;
}
int main(void)
{
int T;
in(T), in(T); get_pri();
W (T--) printf("%d\n", solve());
}