HDU - 5514 Frogs——容斥

版权声明:欢迎大家转载,转载请注明出处 https://blog.csdn.net/hao_zong_yin/article/details/83040317

假设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;
}

猜你喜欢

转载自blog.csdn.net/hao_zong_yin/article/details/83040317