zoukankan      html  css  js  c++  java
  • 「LibreOJ β Round #4」子集

    https://loj.ac/problem/526

    题目描述

    qmqmqm有一个长为 n 的数列 a1,a2,,an,你需要选择集合{1,2,,n}的一个子集,使得这个子集中任意两个元素 i,j 均满足条件 gcd(ai,aj)×gcd(ai+1,aj+1)≠1,其中gcd(i,j)表示最大公约数,且这个子集的元素个数是所有满足上述条件的子集中最多的。输出这个子集的元素个数。

    输入格式

    输入的第一行包含一个正整数nnn。 随后nnn行,每行一个正整数aia_iai​​。

    输出格式

    输出一个整数代表符合条件的元素最多的子集的元素个数。

    样例

    样例输入1

    4
    4
    6
    1
    9

    样例输出1

    3

    样例解释

    选择的子集为{1,2,4}{1,2,4}{1,2,4}。

    样例输入2

    41
    71
    3
    5
    50
    75
    2
    19
    47
    88
    95
    92
    110
    111
    117
    58
    124
    130
    57
    129
    168
    161
    29
    39
    206
    79
    10
    142
    107
    209
    210
    222
    221
    223
    242
    104
    264
    265
    202
    279
    314
    315

    样例输出2

    22


    奇数和奇数、偶数和偶数一定可以选在一起
    所以对于不满足条件的奇数和偶数,连边
    求最大点独立集
    即点数-匹配数

    #include<cstdio>
    #include<iostream>
    #define N 501
    using namespace std;
    typedef long long LL;
    int n;
    LL a[N],b[N];
    bool g[N][N],vis[N];
    int match[N];
    void read(int &x)
    {
        x=0; int f=1; char c=getchar();
        while(!isdigit(c)) { if(c=='-') f=-1;  c=getchar(); }
        while(isdigit(c)) { x=x*10+c-'0'; c=getchar(); }
        x*=f;
    }
    void read(LL &x)
    {
        x=0; int f=1; char c=getchar();
        while(!isdigit(c)) { if(c=='-') f=-1;  c=getchar(); }
        while(isdigit(c)) { x=x*10+c-'0'; c=getchar(); }
        x*=f;
    }
    inline LL gcd(LL p,LL q) { return !q ? p : gcd(q,p%q); }
    bool go(int now)
    {
        for(int i=1;i<=b[0];i++)
        {
            if(vis[i] || !g[now][i]) continue;
            vis[i]=true;
            if(!match[i] || go(match[i]))
            {
                match[i]=now;
                return true;
            }
        }
        return false;
    }
    int main()
    {
        read(n);
        LL x;
        for(int i=1;i<=n;i++)
        {
            read(x);
            (x&1 ? a[++a[0]] : b[++b[0]])=x;
        }
        for(int i=1;i<=a[0];i++)
            for(int j=1;j<=b[0];j++)
                if(gcd(a[i],b[j])==1 && gcd(a[i]+1,b[j]+1)==1) g[i][j]=true;
        int sum=0;
        for(int i=1;i<=a[0];i++)
        {
            fill(vis+1,vis+b[0]+1,0);
            if(go(i)) sum++;
        }
        printf("%d",n-sum); 
    } 


  • 相关阅读:
    AS快捷键的设置
    hausaufgabe--python 23- Recurse 2
    hausaufgabe--python 22- Recurse
    hausaufgabe--python 21_ Lambda
    hausaufgabe--python 20-Closure functions 2
    hausaufgabe--python 20- usage of Closure
    hausaufgabe--python 19- Functions 2
    hausaufgabe--python 18- Defined specific Functions
    hausaufgabe--python 17- Function definition
    hausaufgabe--python 16- Sequenz
  • 原文地址:https://www.cnblogs.com/TheRoadToTheGold/p/7468782.html
Copyright © 2011-2022 走看看