题意
给你一个大小为n的集合,询问每个大小为k的子集的gcd乘积是多少
思路
枚举每一个质因子
p
p
p,计算当前质因子是多少个数的因子,个数记为sum。
当前质因子存在的子集个数为
C
s
u
m
k
C_{sum}^k
Csumk,贡献为
p
C
s
u
m
k
p^{C_{sum}^k}
pCsumk。
优化
上述式中
C
s
u
m
k
C_{sum}^k
Csumk为幂数,可以使用欧拉降幂进行优化
a
b
%
m
o
d
=
a
ϕ
(
m
o
d
)
%
m
o
d
a^{b}\%mod=a^{\phi(mod)}\%mod
ab%mod=aϕ(mod)%mod
注意会爆ll,采用__int128对中间步骤强转。
代码
#include <iostream>
#include <string>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <queue>
#include <iomanip>
#include <map>
#include <cstdio>
#include <stack>
#include <set>
using namespace std;
typedef long long ll;
typedef pair<ll ,ll > pii;
#define endl '\n'
ll gcd(ll a, ll b){
return b == 0 ? a : gcd(b, a % b);
}
void input(){
freopen("in.txt", "r", stdin);
freopen("out.txt", "w", stdout);
}
inline ll read(){
ll x=0,f=1;char c=getchar();
while(c<'0'||c>'9') {if(c=='-') f=-1;c=getchar();}
while (c>='0'&&c<='9') x=(x<<3)+(x<<1)+(c^48),c=getchar();
return x*f;
}
const ll N = 1e7+10, M = 8e4 + 10, inf = 1e8;
ll primes[N], st[N], cnt;
ll t, n, k, mod, phi;
ll mp[M], c[M][32], a[N];
__int128 qpow(__int128 a, __int128 b){
__int128 mod1 = mod;
if(b == 0) return 1;
__int128 ans = 1;
for(; b; b >>= 1){
if(b & 1) ans = ans * a % mod1;
a = a * a % mod1;
}
return ans;
}
void init_p(){ // 线性筛
for(ll i = 2; i < N; i++){
if(st[i] == 0) primes[cnt++] = i;
for(ll j = 0; primes[j] * i < N; j++){
st[primes[j] * i] = 1;
if(i % primes[j] == 0) break;
}
}
}
ll get_phi(ll x){ // 求欧拉函数
ll res = x;
for(ll i = 0; primes[i] * primes[i] <= x; i++){
if(x % primes[i] == 0){
res = res / primes[i] * (primes[i] - 1);
while(x % primes[i] == 0) x /= primes[i];
}
}
if(x > 1) res = res / x * (x - 1);
return res;
}
void init_c(){ // 预处理组合数
for(ll i = 0; i <= n; i++)
for(ll j = 0; j <= min((ll)i, k); j++)
if(j == 0) c[i][j] = 1;
else c[i][j] = (c[i-1][j] + c[i-1][j-1]) % phi;
}
int main(){
ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);
//input();
init_p();
t = read();
while(t--){
n = read(); k = read(); mod = read();
memset(mp, 0, sizeof(mp));
ll maxm = 0;
for(ll i = 1; i <= n; i++){
a[i] = read();
mp[a[i]] ++;
maxm = max(maxm, a[i]);
}
phi = get_phi(mod);
init_c();
ll ans = 1;
for(ll i = 0; primes[i] <= maxm; i++){ // 枚举质因子
ll p = primes[i], res = 0;
for(ll j = p; j <= maxm; j *= p){
ll sum = 0; // 计算在多少个数中出现过
for(ll now = j; now <= maxm; now += j) sum = sum + mp[now];
ans = (__int128) (ans * qpow(p, c[sum][k])) % mod; // 计算贡献
}
}
cout<<ans<<endl;
}
return 0;
}