Moscow Pre-Finals Workshop 2020 - Legilimens+Coffee Chicken Contest (XX Open Cup, Grand Prix of Nanj

这篇博客探讨了两种不同的算法问题,第一部分涉及使用位操作寻找杨辉三角中每一行的奇数数量,第二部分介绍了如何通过离散化处理解决矩形相交划分平面的问题。文章深入解析了二进制位操作在解决问题中的应用,并提供了详细的代码实现。
摘要由CSDN通过智能技术生成

question:

Problem - J - Codeforces 

杨辉三角找每行奇数

thought:

 找二进制中1的数量,在左移1,十进制输出

#include <bits/stdc++.h>

using namespace std;

int main()
{
    long long x;
    int t;
    cin >> t;
    while(t -- )
    {
        cin >> x;
        if(x <= 0)
        {
            cout << 0 << endl;
            continue;
        }
        x --;
        int cnt = 0;
        while(x != 0)
        {
            cnt ++;
            x = x & (x - 1);
        }
        //cout << (1ll << qmi(2, cnt ))<< endl;
     cout << (1ll << cnt) << endl;
     //cout << cnt << endl; 
    }
}

question:

Problem - L - Codeforces

给两个矩形的左下角坐标和右上角坐标,问这两个矩形将平面分成几个非空部分 

thought:

将矩形坐标离散化,构造一个离散化后的矩阵来表示平面,矩形边界的位置标记为1,即不可走,然后dfs搜索连通块即可

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int inf = 0x3f3f3f3f;
const int N = 1e6 + 7;
 
int x[5], y[5], a[5], b[5];
int dir[4][2] = {0, 1, 0, -1, 1, 0, -1, 0};
bool mp[11][11];
 
void dfs(int x, int y)
{
    mp[x][y] = 1;
    for(int i = 0; i < 4; ++i)
    {
        int fx = x + dir[i][0];
        int fy = y + dir[i][1];
        if(fx >= 0 && fx < 11 && fy >= 0 && fy < 11 && !mp[fx][fy])
        {
            dfs(fx, fy);
        }
    }
}
 
int main()
{
    int t;
    scanf("%d", &t);
    while(t--)
    {
        for(int i = 1; i <= 4; ++i)
        {
            scanf("%d%d", &x[i], &y[i]);
            a[i] = x[i];
            b[i] = y[i];
        }
        sort(a + 1, a + 5);    //排序
        sort(b + 1, b + 5);
        for(int i = 1; i <= 4; ++i)    //离散化,乘以2是为了避免矩形长或宽是1,导致矩形内部无法搜到
        {
            x[i] = 2 * (lower_bound(a + 1, a + 5, x[i]) - a);
            y[i] = 2 * (lower_bound(b + 1, b + 5, y[i]) - b);
        }
        memset(mp, 0, sizeof(mp));
        //矩形边界赋为1
        for(int i = x[1]; i <= x[2]; ++i) mp[i][y[1]] = mp[i][y[2]] = 1;
        for(int i = x[3]; i <= x[4]; ++i) mp[i][y[3]] = mp[i][y[4]] = 1;
        for(int i = y[1]; i <= y[2]; ++i) mp[x[1]][i] = mp[x[2]][i] = 1;
        for(int i = y[3]; i <= y[4]; ++i) mp[x[3]][i] = mp[x[4]][i] = 1;
        int ans = 0;
        for(int i = 0; i < 11; ++i)
        {
            for(int j = 0; j < 11; ++j)
            {
                if(!mp[i][j])
                {
                    dfs(i, j);
                    ans++;
                }
            }
        }
        cout<<ans<<'\n';
    }
    return 0;
}
/*
在dev c++中运行
4
0 0 1 1
1 0 2 1
3
0 0 1 1
2 2 3 4
3
1 0 3 2
0 1 2 3
4
0 0 1 1
0 0 1 1
*/

question:

Problem - A - Codeforces 

 

#include <bits/stdc++.h>
using namespace std;
using ll = long long;
const int N = 1e4 + 5;
int n, m;
struct LB
{
    ll b[65];
    void clear() { memset(b, 0, sizeof(b)); }
    void ins(ll x)
    {
        for(int i=62; i>=0; i--)
            if((x>>i)&1)
            {
                if(!b[i]) 
                {
                    b[i] = x;
                    return;
                }
                x ^= b[i];
            }
    }
}A, B;
void solve()
{
    scanf("%d%d", &n, &m);
    ll X = 0;
    A.clear(), B.clear();
    for(int i=1; i<=n; i++)
    {
        ll x, y; scanf("%lld%lld", &x, &y);
        X ^= x;
        A.ins(x^y);
    }
    for(int i=1; i<=m; i++)
    {
        ll x, y; scanf("%lld%lld", &x, &y);
        X ^= x;
        B.ins(x^y);
    }
    ll ans = X;
    for(int i=62; i>=0; i--)
    {
        if(!A.b[i] && !B.b[i]) continue;
        if(!A.b[i]) ans = min(ans, ans^B.b[i]);
        else if(!B.b[i]) ans = max(ans, ans^A.b[i]); 
        else
        {
            if((ans>>i)&1) ans ^= A.b[i]; 
            A.ins(A.b[i]^B.b[i]);
        }
    }
    printf("%lld\n", ans);
}
int main()
{
    int _; scanf("%d", &_);
    while(_--) solve();
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

SUGA no sugar

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值