• cf1043F. Make It One(dp 容斥原理)


    题意

    题目链接

    给出(n)个数,问最少选几个数,使他们的(gcd = 1)

    Sol

    好神仙啊qwq。

    首先,如果答案存在,那么最多为(7)(因为前(7)个质数乘起来(>= 3e5))

    考虑dp,设(f[i][j])表示选了(i)个数,他们(gcd = j)的方案数!

    没错是方案数!

    那么我们只要最后考虑一下(f[i][1])是否有解就行了

    (cnt[i])表示有多少个(a_i)存在(i)这个约数

    转移的时候(f[i][j] = C_{cnt[j]}^i - f[i][j * k], k >= 2)

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<map>
    #include<vector>
    #include<set>
    #include<queue>
    #include<cmath>
    #include<tr1/unordered_map> 
    //#include<ext/pb_ds/assoc_container.hpp>
    //#include<ext/pb_ds/hash_policy.hpp>
    #define Pair pair<int, int>
    #define MP(x, y) make_pair(x, y)
    #define fi first
    #define se second
    //#define int long long
    #define LL long long
    #define ull unsigned long long
    #define rg register
    #define pt(x) printf("%d ", x);
    //#define getchar() (p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, 1<<22, stdin), p1 == p2) ? EOF : *p1++)
    //char buf[(1 << 22)], *p1 = buf, *p2 = buf;
    //char obuf[1<<24], *O = obuf;
    //void print(int x) {if(x > 9) print(x / 10); *O++ = x % 10 + '0';}
    //#define OS  *O++ = ' ';
    using namespace std;
    //using namespace __gnu_pbds;
    const int MAXN = 3e5 + 11, INF = 1e9 + 10, mod = 998244353, Mx = 3e5;
    const double eps = 1e-9;
    inline int read() {
        char c = getchar();
        int x = 0, f = 1;
        while(c < '0' || c > '9') {if(c == '-') f = -1;c = getchar();}
        while(c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar();
        return x * f;
    }
    int N, a[MAXN], f[12][MAXN], cnt[MAXN], fac[MAXN], ifac[MAXN];
    int add(int x, int y) {
        if(x + y < 0) return x + y + mod;
        return x + y >= mod ? x + y - mod : x + y;
    }
    int mul(int x, int y) {
        return 1ll * x * y % mod;
    }
    int C(int N, int M) {
        if(N < M) return 0;
        return mul(fac[N], mul(ifac[M], ifac[N - M]));
    }
    int fp(int a, int p) {
        int base = 1;
        while(p) {
            if(p & 1) base = mul(base, a);
            a = mul(a, a); p >>= 1;
        }
        return base;
    }
    main() {
        N = read();
        for(int i = 1; i <= N; i++) {
            a[i] = read(), cnt[a[i]]++, f[1][a[i]]++;
            if(a[i] == 1) {puts("1"); return 0;}
        }
        fac[0] = 1; for(int i = 1; i <= N; i++) fac[i] = mul(i, fac[i - 1]);
        ifac[N] = fp(fac[N], mod - 2);
        for(int i = N; i >= 1; i--) ifac[i - 1] = mul(i, ifac[i]); 
        for(int i = 1; i <= Mx; i++) 
            for(int j = i + i; j <= Mx; j += i) cnt[i] += cnt[j];
        for(int i = 2; i <= 11; i++) {
            for(int j = Mx; j >= 1; j--) {
                f[i][j] = C(cnt[j], i);
                for(int k = j + j; k <= Mx; k += j) f[i][j] = add(f[i][j], -f[i][k]);
            }
            if(f[i][1] > 0) {printf("%d", i); return 0;}
        }
        puts("-1"); 
        return 0;
    }
    
  • 相关阅读:
    使用yield实现一个协成
    串讲-Python基础练习
    Linux练习
    列表生成式
    Jupyter Notebook的快捷键帮助文档
    mysql字段类型
    爬取12306火车票信息
    【Lodop】02 C-Lodop手册阅读上手
    【Lodop】01 Lodop手册阅读上手
    【Redis】06 事务
  • 原文地址:https://www.cnblogs.com/zwfymqz/p/9874663.html
Copyright © 2020-2023  润新知