假设a和b都是m的因子,设t=lcm(a,b),若t<m,则t也是m的因子
根据这个结论我们可以在m的因子中进行容斥,因子用fac数组保存,设vis[i]为fac[i]需要贡献的数量,num[i]表示fac[i]实际贡献的数量,那么fac[i]应该对答案贡献(等差数列之和)*(vis[i]-num[i]),然后更新后面的因子j(i+1<=j<=因子总数),num[j] += (vis[i]-num[i])
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int maxn = 1e5 + 10;
int T, N, M, a[maxn], n, fac[maxn];
int vis[maxn], num[maxn];
LL cal(int x) {
int cnt = (M-1) / x;
int a1 = x;
int an = x + (cnt-1)*x;
return 1LL*cnt*(a1+an)/2;
}
int main() {
scanf("%d", &T);
for (int ks = 1; ks <= T; ks++) {
scanf("%d%d", &N, &M);
for (int i = 1; i <= N; i++) scanf("%d", &a[i]);
n = 0;
for (int i = 1; i*i <= M; i++) {
if (M % i == 0) {
fac[++n] = i;
if (i * i != M) fac[++n] = M/i;
}
}
sort(fac+1, fac+1+n);
for (int i = 1; i <= n; i++) vis[i] = num[i] = 0;
for (int i = 1; i <= N; i++) {
int x = __gcd(a[i], M);
for (int j = 1; j <= n; j++) {
if (fac[j] % x == 0) vis[j] = 1;
}
}
LL ans = 0;
for (int i = 1; i <= n; i++) {
if (vis[i] == num[i]) continue;
ans += cal(fac[i])*(vis[i]-num[i]);
for (int j = i+1; j <= n; j++) {
if (fac[j] % fac[i] == 0) num[j] += (vis[i]-num[i]);
}
}
printf("Case #%d: %lld\n", ks, ans);
}
return 0;
}