cf练习


(模拟,集合,文氏图)Groups(https://codeforces.com/problemset/problem/1598/B)

题意:n个学生(n为偶数),每个学生都有5个数组来表示他们周一到周五有没有空,问能否将这n个学生分成同样大小的两组,一组再星期a上课,另一组在
星期b上课(a != b)
方法:枚举两个日子i, j, 求在i有空的学生数p和在j有空的学生数q,以及i和j都有空的学生数r,如果p <= n / 2 && q <= n / 2 && p + q + r == n则说明可以

#include
using namespace std;

int g[1010][5];

void solve(){
    int n;
    cin >> n;
    for(int i = 0; i < n; i ++)
        for(int j = 0; j < 5; j ++)
            cin >> g[i][j];
    
    for(int i = 0; i < 5; i ++)
        for(int j = i + 1; j < 5; j ++){
            int a = 0, b = 0, c = 0;
            for(int k = 0; k < n; k ++)
                if(g[k][i] && g[k][j]) c ++;
                else if(g[k][i]) a ++;
                else if(g[k][j]) b ++;
            if(a <= n / 2 && b <= n / 2 && a + b + c == n){
                cout << "YES" << endl;
                return;
            }
        }
    cout << "NO" << endl;
}

int main(){
    int t;
    cin >> t;
    while(t --) solve();
}

(数学)Luntik and Concerts(https://codeforces.com/problemset/problem/1582/A)

题意:a个1,b个2,c个3,问将他们分成两份,最小的差是多少
方法:sum = a + 2b + 3c, 那么可以构造出1到sum的所有值,如果sum=偶数,则差为0,否则差为1

#include
using namespace std;

#define int long long

void solve(){
    int a, b, c;
    cin >> a >> b >> c;
    int d = a + b * 2 + c * 3;
    cout << d % 2 << endl;
}

signed main(){
    int t;
    cin >> t;
    while(t --) solve();
}

(组合数学)Luntik and Subsequences(https://codeforces.com/problemset/problem/1582/B)

题意:给你长度为n的串,和为sum,问所有和为sum - 1的串的个数有多少
方法:统计1的个数cnt1和0的个数cnt0,答案为cnt1 * (1 << cnt0)

#include
using namespace std;

#define int long long

void solve(){
    int n;
    cin >> n;
    vector a(n);
    for(auto &i : a) cin >> i;
    int cnt0 = count(a.begin(), a.end(), 0);
    int cnt1 = count(a.begin(), a.end(), 1);
    cout << ((int)1 << cnt0) * cnt1 << endl;
}

signed main(){
    int t;
    cin >> t;
    while(t --) solve();
} 
CF