九校聯考DAY2T2(中國剩餘定理,積性篩)
阿新 • • 發佈:2019-02-01
題目描述
整除符號為 |,d|n 在計算機語言中可被描述為 n%d == 0。
現有一算式 n| - x,給定 n,m,求 [1, n] 以內 x 解的個數。
解可能很大,輸出取模 998244353。
輸入格式
其中 n 的給定方式是由 c 個不超過 t 的質數的乘積給出的,c 和 t 的範圍會在資料範圍中給出。
第一行一個 id 表示這個資料點的標號。
多組資料,其中第二行一個整數 T 表示資料組數。對於每一組資料:
第一行兩個整數 c 和 m。
第二行 c 個整數,這些整數都是質數,且兩兩不同,他們的乘積即為n。
由於你可以通過輸入求出 t,輸入不再給出。
輸出格式
對於每組資料輸出一行,表示解的個數。
樣例資料
input
0
1
2 3
2 3
output
6
資料規模與約定
其中所有資料點都滿足 1 ≤ c ≤ 50,1 ≤ t ≤ ,1 ≤ m ≤ ,1 ≤ T ≤10000。
時間限制:
空間限制:
中國剩餘定理求方案數
暴力是對每個方程用快速冪枚舉出可能解最後乘起來,80分
優秀的做法是用積性函式優化掉合數的快速冪,AC
#include<bits/stdc++.h>
using namespace std;
#define rep(i,j,k) for(int i = j;i <= k;++i)
#define repp(i,j,k) for(int i = j;i >= k;--i)
#define rept(i,x) for(int i = linkk[x];i;i = e[i].n)
#define P pair<int,int>
#define Pil pair<int,ll>
#define Pli pair<ll,int>
#define Pll pair<ll,ll>
#define pb push_back
#define pc putchar
#define mp make_pair
#define file(k) memset(k,0,sizeof(k))
#define ll long long
const int p = 998244353;
int t[60];
int num[60];
int ans;
int c,m;
int prime[11000] , tot;
bool flag[10010];
int read()
{
int sum = 0;char c = getchar();bool flag = true;
while(c < '0' || c > '9') {if(c == '-') flag = false;c = getchar();}
while(c >= '0' && c <= '9') sum = sum * 10 + c - 48,c = getchar();
if(flag) return sum;
else return -sum;
}
int Pow(int a,int x,int p)
{
int sum = 1;
while(x)
{
if(x & 1) sum = 1ll * sum * a % p;
a = 1ll * a * a % p;
x >>= 1;
}
return sum;
}
int mi[10100];
void work(int m,int n,int x)
{
memset(flag,0,sizeof(flag));tot = 0;
rep(i,2,n - 1)
{
if(!flag[i])
{
prime[++tot] = i;
mi[i] = Pow(i,m,n);
}
rep(j,1,tot)
{
if(prime[j] * i > n) break;
flag[prime[j] * i] = true;
mi[prime[j]*i] = mi[prime[j]] * mi[i] % n;
if(i % prime[j] == 0) break;
}
num[x] += mi[i] == i;
}
}
void print(int x)
{
if(x < 0) {putchar('-');x = -x;}
if(x >= 10) {
print(x / 10);
}
putchar('0' + x % 10);
}
void init()
{
c = read(),m = read();ans = 1;
rep(i,1,c) t[i] = read(),num[i] = 2,work(m,t[i],i),ans = 1ll*ans*num[i]%p;
print(ans);putchar('\n');
}
int main()
{
freopen("division.in","r",stdin);
freopen("division.out","w",stdout);
int T = read();T = read();
while(T--) init();
return 0;
}