牛客周赛 round105 (A-F)题解

牛客链接

A

思路

掌握 x^0=x 这个性质就可以秒了

题解

复制代码
#include <bits/stdc++.h>
using namespace std;
const int N=1e5+10;
typedef long long ll;
int t,n;
int k;

int main()
{
    ios::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);
    cin>>k;
    cout<<k<<' '<<0<<endl;
    return 0;
}

B

思路

按照题目意思模拟即可

题解

复制代码
#include <bits/stdc++.h>
using namespace std;
const int N=1e5+10;
typedef long long ll;
int t,n;
int b[N];
int a[N];

int main()
{
    ios::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);
    cin>>n;
    for(int i=0;i<n;i++)cin>>a[i];
    for(int i=1;i<n;i++)b[i]=a[i]^a[i-1];
    int ans=b[1];
    for(int i=2;i<n;i++)ans=__gcd(ans,b[i]);
    cout<<ans<<endl;


    return 0;
}

C

思路

猜结论,只要对角线放置就可以保证一次加2,又发现无论如何最后的sum之和都只会是偶数,于是猜测奇数的情况下无法构造,那么偶数只需要对角线摆放。

题解

复制代码
#include <bits/stdc++.h>
using namespace std;
const int N=1e5+10;
typedef long long ll;
int t,n;
int k;

int main()
{
    ios::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);
    cin>>n>>k;
    if(k%2==1)cout<<-1<<endl;
    else
    {
        int x = k/2;
        for(int i=0;i<n;i++)
        {
            for(int j=0;j<n;j++)
            {
                if(i==j&&i<x)cout<<1;
                else cout<<0;
            }
            cout<<endl;
        }
    }


    return 0;
}

D

思路

有点小麻烦,但是不难想出怎么做,主要难在模拟上了,看卡里有4种情况需要考虑11,12,22,21,实际上只需要考虑11,12,22就行,如我代码所示,最后是由结果可以是由22222...121212...1111 三部分构成,所以只会出现11,12,22三种情况,然后就是计算结果的方式了,显然22在一起可以使n-1的基础上+1,所以看代码模拟即可

题解

复制代码
#include <bits/stdc++.h>
using namespace std;
const int N=1e5+10;
typedef long long ll;
int t,n;
int k;
int cnt[3];
int main()
{
    ios::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);
    cin>>n>>k;
    for(int i=0;i<n;i++)
    {
        int x;
        cin>>x;
        cnt[x]++;
    }
    int xx = k-n+1;
    
    int minx=0;
    if(cnt[1]+1>=cnt[2])minx = n-1;
    else minx = n-1+(cnt[2]-cnt[1]-1);

    int maxx = cnt[1]+(cnt[2]-1)*2;
//     cout<<minx<<' '<<maxx<<endl;
    if(k<minx||k>maxx)cout<<-1<<endl;
    else 
    {
        for(int i=0;i<=xx;i++)
        {
            cout<<2<<' ';
            cnt[2]--;
        }
        for(int i=0;i<cnt[2];i++)
        {
            cout<<1<<' '<<2<<' ';
            cnt[1]--;
        }
        for(int i=0;i<cnt[1];i++)
        {
            cout<<1<<' ';
        }
        cout<<endl;
    }



    return 0;
}

// 10 15
// 1 2 1 2 2 2 2 2 2 2

E

思路

考虑每一个节点的的所有的邻居的每一个二进制位分别进行计算0和1的个数,当中心节点的第i个二进制位为0,那么此时要使得无进制的三个数字累加最后结果是1,显然就是一个邻居节点为0,一个邻居节点为1的情况,所以此时的所有可能就是$$cnt =cnt0*cnt1$$,如果说中心节点的第i个二进制位为1,那么次数要使得最后三个数字的累加结果是1,显然就是两个邻居节点同时是0,或者两个邻居节点同时是1,次数的计算方式就是$$ cnt = C2_{cnt0}+C2_{cnt1}$$,最后计算ans就是将第i位代表的十进制数字×cnt累加取模即可

题解

复制代码
#include <bits/stdc++.h>
const int N = 2e5+10;
const int mod = 998244353 ;
typedef long long ll;
using namespace std;
int n,m;
ll ans=0;
vector<int>graph[N];
int w[N];
int main()
{
    cin>>n>>m;
    for(int i=1;i<=n;i++)cin>>w[i];
    for(int i=0;i<m;i++)
    {
        int u,v;
        cin>>u>>v;
        graph[u].push_back(v);
        graph[v].push_back(u);
    }
    for(int i=0;i<=30;i++)
    {
        ll xx = (1<<i);
        ll cnt=0;
        for(int j=1;j<=n;j++)
        {
            ll cnt0=0;
            ll cnt1=0;
            for(auto k:graph[j])
            {
                if((w[k]>>i)&1)cnt1++;
                else cnt0++;
            }
            if((w[j]>>i)&1)
            {
                cnt = (cnt+(cnt0*(cnt0-1)/2)%mod + (cnt1*(cnt1-1)/2)%mod)%mod;
            }
            else 
            {
                cnt = (cnt+cnt0*cnt1)%mod;
            }
        }
        ll curans = (xx*cnt)%mod;
        ans = (ans+curans)%mod;
    }
    cout<<ans<<endl;
    return 0;
}

F

思路

动态规划求解,bool dp[i][j][k]表示前面i个数的最大公约数位j,此时的累加和为k是否成立,首先观察可知m的大小限制在1到50,所以我们可以考虑预处理1-50的约数,进入循环后,初始化dp和path数组,path数组用于保存每个节点的j,用于最后的有答案输出,那么接下来的部分看代码就能看懂了,三重循环遍历

题解

复制代码
#include <bits/stdc++.h>
using namespace std;
const int N = 51;
const int MAX_X = 2501;
vector<int> divx[N];
bool dp[N][N][MAX_X];
int path[N][N][MAX_X];
int n,m,x;
void precom(int x)
{
    for(int i=1;i<=x;i++)
    {
        for(int j=i;j<=x;j+=i)
        {
            divx[j].push_back(i);
        }
    }
}

int main()
{
    int t;
    cin>>t;
    precom(50);
    while(t--)
    {
        cin>>n>>m>>x;
        memset(dp,false,sizeof(dp));
        memset(path,0,sizeof(path));
        for(int i=1;i<=m;i++){if(i<=x)dp[1][i][i]=true;}
        for(int i=1;i<n;i++)
        {
            for(int j=1;j<=m;j++)
            {
                for(int k=1;k<=x;k++)
                {
                    if(dp[i][j][k])
                    {
                        for(auto g:divx[j])
                        {
                            if(g+k<=x)
                            {
                                dp[i+1][g][g+k]=true;
                                path[i+1][g][g+k]=j;
                            }
                        }
                    }
                }
            }
        }
        int preg = -1;
        for(int i=1;i<=m;i++)
        {
            if(dp[n][i][x])
            {
                preg=i;
                break;
            }
        }
        if(preg==-1)cout<<-1<<endl;
        else 
        {
            int curx=x;
            int curg=preg;
            vector<int>a(n+1);
            for(int i=n;i>=1;i--)
            {
                a[i]=curg;
                if(i>1)
                {
                    preg = path[i][curg][curx];
                    curx = curx - curg;
                    curg = preg;
                }
            }
            for(int i=1;i<=n;i++)cout<<a[i]<<' ';
            cout<<endl;
        }
    }
    
}
相关推荐
Joker-01111 个月前
牛客周赛Round 99(Go语言)
go·牛客周赛
机智可爱嚎嚎6 个月前
牛客周赛 Round 80
c++·学习·算法·蓝桥杯·牛客周赛