二分出一个 x x x, 检查 小于等于 x x x 的有多少数字,
可以想到将每个 S ( n i ) S(n_i) S(ni) 中 小于等于 x x x 的数字个数计算出来, 然后减去 重复 的,
小于等于 x x x 的数字个数可以通过 二分 计算出来,
对于 重复 的, 对每个 n a , n b n_a, n_b na,nb 减去 S ( L c m ( n a , n b ) ) S(Lcm(n_a, n_b)) S(Lcm(na,nb)), 加上 S ( L c m ( n a , n b , n c ) ) S(Lcm(n_a, n_b, n_c)) S(Lcm(na,nb,nc)) 再减去 …
于是对于每个 S ( n i ) S(n_i) S(ni), 都对应着一个 容斥系数 f [ n i ] f[n_i] f[ni],
现在去计算 f [ n i ] f[n_i] f[ni] 是多少, 可以使用 dp, 设 F [ i , j ] F[i, j] F[i,j] 表示前 i i i 个数组成的集合中 j j j 的 容斥系数 是多少,
则 F [ i , L c m ( j , A i ) ] = F [ i − 1 , L c m ( j , A i ) ] − ∑ F [ i − 1 , j ] F[i, Lcm(j, A_i)] = F[i-1, Lcm(j, A_i)] - \sum F[i-1, j] F[i,Lcm(j,Ai)]=F[i−1,Lcm(j,Ai)]−∑F[i−1,j] .
于是就可以 O ( q log 3 1 0 17 ) O(q \log^3 10^{17}) O(qlog31017) 计算答案了 .
#include
#define reg register
typedef long long ll;
int read(){
char c;
int s = 0, flag = 1;
while((c=getchar()) && !isdigit(c))
if(c == '-'){ flag = -1, c = getchar(); break ; }
while(isdigit(c)) s = s*10 + c-'0', c = getchar();
return s * flag;
}
const int maxn = 205;
int M;
int K;
int A[maxn];
ll F[maxn][70];
int Gcd(int a, int b){ return !b?a:Gcd(b, a%b); }
int Lcm(int a, int b){ return a/Gcd(a, b)*b; }
bool Ksmcompar(ll a, int b, ll x){
ll s = 1;
while(b){
if(b & 1){
if(s > x/a) return 0;
s *= a;
}
b >>= 1;
if(a > x/a && b) return 0;
a *= a;
}
return 1;
}
ll chk(ll x){
ll res = 0;
for(reg int i = 1; i <= 60; i ++){
if(!F[K][i]) continue ;
ll l = 0, r = 1e17, s = 0;
while(l <= r){
//printf("%lld %lld %lld\n", x, l, r);
ll mid = l+r >> 1ll;
if(Ksmcompar(mid, i, x)) l = mid + 1, s = mid;
else r = mid - 1;
}
// printf("FUck %lld\n", s-1);
res += 1ll*F[K][i]* (s-1);
}
return res+1; // !
}
void Work(){
M = read(), K = read();
for(reg int i = 1; i <= K; i ++) A[i] = read();
memset(F, 0, sizeof F);
for(reg int i = 1; i <= K; i ++){
for(reg int j = 1; j <= 60; j ++) F[i][j] = F[i-1][j];
F[i][A[i]] ++;
for(reg int j = 1; j <= 60; j ++){
int to = Lcm(A[i], j);
if(!F[i-1][j] || to > 60) continue ;
F[i][to] -= F[i-1][j];
}
}
ll l = 1, r = 1e17, Ans = 1;
while(l <= r){
ll mid = l+r >> 1;
if(chk(mid) >= M) Ans = mid, r = mid - 1;
else l = mid + 1;
}
printf("%lld\n", Ans);
}
int main(){
int T = read(); while(T --) Work();
return 0;
}