HDU - 5514 Frogs——容斥
阿新 • • 發佈:2018-11-16
假設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; }