2022牛客五一集训派对day1(E、H)

E-Touring cities

链接:https://ac.nowcoder.com/acm/contest/33549/E
来源:牛客网
题目:
Niuniu wants to tour the cities in Moe country. Moe country has a total of nm cities. The positions of the cities form a grid with n rows and m columns. We represent the city in row x and column y as (x,y). (1 ≤ x ≤ n,1 ≤ y ≤ m) There are bidirectional railways between adjacent cities. (x1,y1) and (x2,y2) are called adjacent if and only if |x1-x2|+|y1-y2|=1. There are also K bidirectional air lines between K pairs of cities. It takes Niuniu exactly one day to travel by a single line of railway or airplane. Niuniu starts and ends his tour in (1,1). What is the minimal time Niuniu has to travel between cities so that he can visit every city at least once?
Note that the air line may start and end in the same city.
题意:
给一个n
m的矩形,相邻的方格之间连边,在给k组x1,y1,x2,y2(x1,y1)和(x2,y2)连边,从(1,1)走到(1,1),需要经过所有的方格每次移动一个方格需要1天时间,输出走完这些的最小的天数。
思路:
通过画图自己手动模拟可以发现当n和m不同时为奇数的时候输出nm就是答案,当n和m都为奇数的时候,发现可以构造出nm+1的答案,我们把整张图从(1,1)开始黑白染色当两个黑色块之间有一条边的情况是这个图还是可以构成哈密顿回路既答案可以为n*m,所以我们只需要判断是否有两个黑块存在边就行。
以下为ac代码:

#include<bits/stdc++.h>
typedef long long ll;
typedef unsigned long long ull;
#define int ll
#define pii pair<int,int>
using namespace std;
const double pi=acos(-1.0);
const double eps=1e-8;
const int mod=1e9+7;
const int INF=0x3f3f3f3f;
const int LINF=0x3f3f3f3f3f3f3f3f;
const int MAXN=2e5+10;
void solve()
{
    int n,m,k;
    cin>>n>>m>>k;
    if((n&1)&&(m&1))
    {
        int ans=n*m+1;
        int flag=0;
        for(int i=1;i<=k;++i)
        {
            int x1,y1,x2,y2;
            cin>>x1>>y1>>x2>>y2;
            if(x1==x2&&y1==y2) continue;
            if(x1%2==y1%2&&x2%2==y2%2) flag=1;
        }
        cout<<ans-flag<<"\n";
    }
    else
    {
        for(int i=1;i<=k;++i)
        {
            int x1,y1,x2,y2;
            cin>>x1>>y1>>x2>>y2;
        }
        int ans=n*m;
        cout<<ans<<"\n";
    }
}
signed main()
{
    std::ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    int _=1;
    cin>>_;
    for(int i=1; i<=_; ++i)
    {
        solve();
    }
    return 0;
}
/*
*/

H-Playing games

链接:https://ac.nowcoder.com/acm/contest/33549/H
来源:牛客网
题目:
Niuniu likes playing games. He has n piles of stones. The i-th pile has ai stones. He wants to play with his good friend, UinUin. Niuniu can choose some piles out of the n piles. They will play with the chosen piles of stones. UinUin takes the first move. They take turns removing at least one stone from one chosen pile. The player who removes the last stone from the chosen piles wins the game. Niuniu wants to choose the maximum number of piles so that he can make sure he wins the game. Can you help Niuniu choose the piles?
题意:
给定n个数字,从中选出k个然后Niuniu和Uinuin玩尼姆游戏在保证Niuniu必赢的情况下输出最大的k如果Niuniu不能必赢则输出0,其中Niuniu后手
思路:
尼姆游戏后手必赢的情况所有数字的异或和为0,所以我们要选出尽可能多少数字使得他们的异或和为0。我们把所有的数字全部异或起来得到一个异或和sum,然后我们只需要找出最少的数字异或和为sum就行,把n-最少的数字就是最终答案。对于每个数字我们只有选或者不选两种情况,这就是背包由此我们可以写出dp方程式dp[i][j]代表前i个数字异或和为j的情况下选的最少的个数这个dp可以用滚动数组压掉一维。这样的复杂度显然是通过不了的,观察后发现当sum=0时可以直接输出答案n-1,把每个数字a去跟sum异或如果存在sum^a这个值我们可以直接输出n-2,剩下的情况去跑dp,注意dp第二维一定要开(1<<19)不然会炸空间,至于这样为什么能过其实我也不太懂,感觉数字一多必然会出现1和2这两种情况(猜测),数字少的话就让它跑dp,赛后看了大家过得好像都是fwt,但是本人太弱了不会写fwt,如果有大佬能hack的话把数据贴贴。
以下为ac代码:

#include<bits/stdc++.h>
typedef long long ll;
typedef unsigned long long ull;
#define int ll
#define pii pair<int,int>
using namespace std;
const double pi=acos(-1.0);
const double eps=1e-8;
const int mod=1e9+7;
const int INF=0x3f3f3f3f;
const int LINF=0x3f3f3f3f3f3f3f3f;
const int MAXN=5e5+10;
int a[MAXN];
int vis[MAXN];
vector<int>v;
int dp[2][1<<19];
void solve()
{
    int n;
    cin>>n;
    int sum=0;
    for(int i=1; i<=n; ++i)
    {
        cin>>a[i];
        if(!vis[a[i]]) v.push_back(a[i]);
        vis[a[i]]++;
        sum^=a[i];
    }
    if(sum==0) cout<<n;
    else
    {
        if(vis[sum])
        {
            cout<<n-1;
            return ;
        }
        for(int x:v)
        {
            if(vis[sum^x])
            {
                cout<<n-2;
                return ;
            }
        }
        for(int i=0;i<=1;++i)
        {
            for(int j=0;j<(1<<19);++j)
            {
                dp[i][j]=1e18;
            }
        }
        dp[0][0]=0;
        for(int i=0;i<v.size();++i)
        {
            for(int j=0;j<(1<<19);++j)
            {
                if(dp[i%2][j]==1e18) continue;
                dp[(i+1)%2][j]=min(dp[(i+1)%2][j],dp[i%2][j]);
                dp[(i+1)%2][j^v[i]]=min(dp[(i+1)%2][j^v[i]],dp[i%2][j]+1);
            }
        }
        cout<<max(0ll,n-dp[v.size()%2][sum]);
    }
}
signed main()
{
    std::ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    int _=1;
    //cin>>_;
    for(int i=1; i<=_; ++i)
    {
        solve();
    }
    return 0;
}
/*
*/
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值