牛客练习赛67 赛后复盘

比赛链接

A

  • A 签到,模拟
    题意:
    找出字符串(可能有空格)中所有的数,不能有前导0,“00000”输出0。
#include <bits/stdc++.h>
using namespace std;
string s;
int main() {
    ios::sync_with_stdio(false);cin.tie(0);cout.precision(10);cout << fixed;
#ifdef LOCAL_DEFINE
    freopen("input.txt", "r", stdin);
#endif
    while(getline(cin,s)) {
        vector<int> temp;
        for(char c:s){
            if(c>='0' && c<='9'){
                int num=int(c-'0');
                temp.emplace_back(num);
            } else{
                if(c==' ') continue;
                bool flag=true;
                if(int(temp.size())!=0){
                    for(int i=0; i<int(temp.size()); ++i) {
                        int x=temp[i];
                        if(x!=0) flag=false;
                        if(flag && x==0 && i!=int(temp.size())-1) continue;
                        cout<<x;
                    }
                    cout<<' ';
                    temp.clear();
                }
            }
        }
        if(int(temp.size())!=0){
            bool flag=true;
            for(int i=0; i<int(temp.size()); ++i) {
                int x=temp[i];
                if(x!=0) flag=false;
                if(flag && x==0 && i!=int(temp.size())-1) continue;
                cout<<x;
            }
        }
        cout<<'\n';
    }
#ifdef LOCAL_DEFINE
    cerr << "Time elapsed: " << 1.0 * clock() / CLOCKS_PER_SEC << " s.\n";
#endif
    return 0;
}

B

  • B
    签到
    题意:
    给你n个数,让你找几个数做&操作,得出来的数最大。
    思路:
    拍个序,最大的那个数就是答案,因为和其他数&肯定是亏的。
#include <bits/stdc++.h>
using namespace std;
#define ll long long
const int maxn=(int)1e5+100;
ll tc,n,a[maxn],bit[100];
int main() {
    ios::sync_with_stdio(false);cin.tie(0);cout.precision(10);cout << fixed;
#ifdef LOCAL_DEFINE
    freopen("input.txt", "r", stdin);
#endif
    cin>>tc;
    while(tc--){
        memset(bit,0,sizeof(bit));
        cin>>n;
        for(int i=0; i<n; ++i){
            cin>>a[i];
        }
        sort(a, a+n);
        cout<<a[n-1]<<'\n';
    }
#ifdef LOCAL_DEFINE
    cerr << "Time elapsed: " << 1.0 * clock() / CLOCKS_PER_SEC << " s.\n";
#endif
    return 0;
}

C

  • C
    博弈,必胜必败态打表,规律
    题意:
    有n个石子,轮流取,可取的数目为2的n次,1,2,4,8,…,每人都采取最优策略,问谁能赢。
    思路:
    看了大佬说可以想到2的n次对3取模的规律,我反正想不到,没那智商就只能打表了找规律了,必胜必败态打表代码在注释里。
#include <bits/stdc++.h>
using namespace std;
int tc,n,dp[1000];
int main() {
    ios::sync_with_stdio(false);cin.tie(0);cout.precision(10);cout << fixed;
#ifdef LOCAL_DEFINE
    freopen("input.txt", "r", stdin);
#endif
    cin>>tc;
    while(tc--){
        cin>>n;
        if(cnt%3!=0) cout<<"Alan"<<'\n';
        else cout<<"Frame"<<'\n';
    }
//    dp[0]=0;
//    dp[1]=1;
//    dp[2]=1;
//    dp[3]=0;
//    dp[4]=1;
//    dp[5]=1;
//    for(int i=6; i<=40; ++i){
//        for(int j=0;(1<<j)<=i;++j){
//            int temp=i-(1<<j);
//            if(dp[temp]==0) dp[i]=1;
//        }
//    }
//    for(int i=1; i<=30; ++i) cout<<i<<' '<<dp[i]<<endl;
#ifdef LOCAL_DEFINE
    cerr << "Time elapsed: " << 1.0 * clock() / CLOCKS_PER_SEC << " s.\n";
#endif
    return 0;
}

D


dp,01翻转(单个,1~n)

  • D
    题意:
    给你长度为n的01序列,现在你可以做两种操作。
    1.把某个数翻转。
    2.把前1~x个数翻转。
    现在问你做多少次才能变成全是0的序列。
    思路:
    dp。
    维护前n个都变成0和1的最少次数。
#include <bits/stdc++.h>
using namespace std;
const int maxn=(int)1e5+100;
const int INF=0x3f3f3f3f;
int n,a[maxn],c1[maxn],c0[maxn];
int main() {
    ios::sync_with_stdio(false);cin.tie(0);cout.precision(10);cout << fixed;
#ifdef LOCAL_DEFINE
    freopen("input.txt", "r", stdin);
#endif
    cin>>n;
    memset(c0,INF,sizeof(c0));
    memset(c1,INF,sizeof(c1));
    c0[0]=c1[0]=0;
    for(int i=1; i<=n; ++i){
        cin>>a[i];
        if(a[i]==1) {
            c0[i]=min(c0[i-1]+1, c1[i-1]+1);
            c1[i]=min(c1[i-1], c0[i-1]+1);
        } else if(a[i]==0){
            c0[i]=min(c0[i-1], c1[i-1]+1);
            c1[i]=min(c1[i-1]+1, c0[i-1]+1);
        }
    }
    cout<<min(c0[n], c1[n]+1)<<'\n';
#ifdef LOCAL_DEFINE
    cerr << "Time elapsed: " << 1.0 * clock() / CLOCKS_PER_SEC << " s.\n";
#endif
    return 0;
}

E

  • E
    最短路,用位建图,新奇!
    题意:
    给你n个数ai,现在让你从1号点走到n号点,首先如果a[i]&a[j]!=0的话,i到j才有一条无向边,否则他俩之间就没边,代价是lowbit(a[i]&a[j])现在问你从1走到n的最小花费是多少。不能到达就输出impossible。
    思路:
    位思想。
    从来没做过用位建图的,学到了。
    对于每个a[i],如果i位上是1,那就连一条a[i]到i位那个点的单向边,长度为(1<<i),然后连一条i位那个点到a[i]的单向边,长度为0。然后就没了,整个图跑个dijkstra就完事了。
#include <bits/stdc++.h>
#define ll long long
using namespace std;
const int maxn = 40*100000+100; //点数
const ll INF = 0x3f3f3f3f3f3f3f3fLL;
ll tc,n,a[maxn],bit[40];
struct node {
    int id;
	ll w;
    node(){}
    node(int a, ll b) : id(a), w(b) {} //hdu6805 美好的回忆:>
    friend bool operator < (node a, node b) {return a.w > b.w;}
};
vector<node> G[maxn];
bool vis[maxn];
ll dis[maxn];
void dij(int s, int n) {
    priority_queue<node> q;
	while (!q.empty()) q.pop();
    node cur;
    for (int i = 1; i <= n; ++i) {
		dis[i] = INF;
		vis[i] = 0;
	}
    dis[s] = 0;
    q.push(node(s, dis[s]));
    while (!q.empty()) {
        cur = q.top();
        q.pop();
        if (vis[cur.id]) continue;
        vis[cur.id] = 1;
        for (node to : G[cur.id]) {
            if (!vis[to.id] && dis[to.id] > dis[cur.id] + to.w) {   //dis[to.id] > to.w 就变成了堆优化prim
                dis[to.id] = dis[cur.id] + to.w;
                q.push(node(to.id, dis[to.id]));
            }
        }
    }
}
void init(int n) {
    for (int i = 0; i <= n; ++i) G[i].clear();
}
int main() {
    ios::sync_with_stdio(false);cin.tie(0);cout.precision(10);cout << fixed;
#ifdef LOCAL_DEFINE
    freopen("input.txt", "r", stdin);
#endif
    cin>>tc;
    while(tc--){
        cin>>n;
        init(40*100000+10);
        memset(bit,0,sizeof(bit));
        for(int i=1; i<=n; ++i){
            cin>>a[i];
            ll ta=a[i], now=0;
            while(ta>0){
                if(ta%2==1) {
                    G[i].emplace_back(node(n+1+now, (1LL<<now)));
                    G[n+1+now].emplace_back(node(i, 0));
                    bit[now]++;
                }
                ++now;
                ta/=2;
            }
        }
        dij(1, n+60);
        if(dis[n]==INF) cout<<"Impossible"<<'\n';
        else cout<<dis[n]<<'\n';
    }
#ifdef LOCAL_DEFINE
    cerr << "Time elapsed: " << 1.0 * clock() / CLOCKS_PER_SEC << " s.\n";
#endif
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值