河南萌新联赛2024第(四)场:河南理工大学

B题--小雷的神奇电脑

B-小雷的神奇电脑_河南萌新联赛2024第(四)场:河南理工大学 (nowcoder.com)

在比赛的时候就想出了解决办法,只不过跟题解想的方法不同,也是先将数组排序,只不过我不是通过异或之后再求同或,我是将相邻的两个数字转会为二进制01字符串,而后按照题目中给的方式求出上述两个字符串同或后的字符串,再将同或后的字符串转化为数字,比较数字的大小。但是将将循环的结束条件写错了,真的是很蠢了,错了那么多发都没有找到问题!!!结束之后再按照题解的思路写的时候,立马反映出了问题,有点想骂自己一句好蠢。

#include<bits/stdc++.h>
using namespace std;
#define int long long
int n,m;
int a[200005];
signed main(){
    std::ios::sync_with_stdio(0);
    std::cin.tie(0);
    cin>>n>>m;
    for(int i=1;i<=n;i++){
        cin>>a[i];
    }
    sort(a+1,a+1+n);
    int mm=0;
    int j=0;
    for(int i=1;i<n;i++){
        int x=a[i];
        //cout<<x<<endl;
        int y=a[i+1];
        string s1="";
        string s2="";
        int zz=m;
        while(zz--){
            if(x%2==0) s1='0'+s1;
            else s1='1'+s1;
            if(y%2==0) s2='0'+s2;
            else s2='1'+s2;
            x/=2;
            y/=2;
        }
        
        string s3="";
        for(int i=0;i<s1.size();i++){
            if(s1[i]==s2[i]) s3=s3+'1';
            else s3=s3+'0';
        }
        //cout<<"s3="<<s3[0]<<endl;
        int ans=1;
        int sum=0;
        int k=s3.size()-1;
        for(int i=k;i>=0;i--){
            if(s3[i]=='1') sum+=ans;
            ans*=2;
        }
        if(sum>mm) mm=sum;
        
    }
    cout<<mm<<endl;
}

题解的思路:事先将30以内的数字求出来,将他们存入一个数组sum中,然后将题目中的数组读入并排序,然后求出相邻两个数的以后和最小值kk(异或和最小,不同数位的和最小,相同数位的和越大)。然后将sum[m-1]-kk即为答案。

#include<bits/stdc++.h>
using namespace std;
#define int long long
int n,m;
int a[200005];
int sum[35];
int inf=2000000000;//这个数一定要开的足够大,不然会过不了
signed main(){
    std::ios::sync_with_stdio(0);
    std::cin.tie(0);
    sum[0]=1;
    int ans=1;
    for(int i=1;i<=30;i++){
        ans*=2;
        sum[i]=ans+sum[i-1];
    }
    cin>>n>>m;
    for(int i=1;i<=n;i++){
        cin>>a[i];
    }
    sort(a+1,a+1+n);
    int mm=inf;
    for(int i=1;i<n;i++){
        int x=a[i];
        int y=a[i+1];
        mm=min(mm,x^y);
    }
    ans=sum[m-1]-mm;
    cout<<ans<<endl;
}

I题--马拉松

I-马拉松_河南萌新联赛2024第(四)场:河南理工大学 (nowcoder.com)

比赛的时候想到了解法,但是很蠢的是自己没有写明白链式前向星,存图没存明白,然后就又一次举白旗了。实际上这道题将两个点相邻的每一个点有多少个连接点,然后两者相乘。

如图,如果1跟3是x跟y的位置,那么就是4x4=16路况的马拉松不能跑。

看了别人的代码,想明白了,发现自己对图的dfs也不是很了解,即使比赛的时候将存图写明白了也有可能会在dfs上出问题。

#include<bits/stdc++.h>
using namespace std;
#define int long long
int n,x,y;
int sum[300005];
int cnt[300005];
vector<int> ve[300005];
void dfs(int x,int fa){
    sum[x]=1;
    if(x==y) cnt[x]=true;
    for(auto dg:ve[x]){
        if(dg==fa) continue;
        dfs(dg,x);
        sum[x]+=sum[dg];
        if(cnt[dg]) cnt[x]=true;
    }
}
signed main(){
    std::ios::sync_with_stdio(0);
    std::cin.tie(0);
    cin>>n>>x>>y;
    for(int i=1;i<n;i++){
        int a,b;
        cin>>a>>b;
        ve[a].push_back(b);
        ve[b].push_back(a);
    }
    dfs(x,0);
    int ans=0;
    for(auto cg:ve[x]){
        if(cnt[cg]) ans+=sum[cg];
    }
    cout<<sum[y]*(sum[x]-ans)<<endl;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值