牛客练习赛67 (A、B、C、D、E)

A、 牛牛爱字符串

思路

getline读取,把非数字的字符跳过,字符串处理数字,然后删除前导 0 0
注意特判一下 0 , 00 , 000 0,00,000 这种情况

参考代码

#pragma GCC optimize(2)
#include<bits/stdc++.h>
using namespace std;
const int man = 2e5+10;
#define IOS ios::sync_with_stdio(0)
#define ull unsigned ll
#define uint unsigned
#define pai pair<int,int>
#define pal pair<ll,ll>
#define IT iterator
#define pb push_back
#define fi first
#define se second
#define For(i,j,k) for (int i=(int)(j);i<=(int)(k);++i)
#define Rep(i,j,k) for (int i=(int)(j);i>=(int)(k);--i)
#define endl '\n'
#define ll long long
const ll mod = 1e9+7;

signed main() {
	#ifndef ONLINE_JUDGE
		//freopen("in.txt", "r", stdin);
		//freopen("out.txt","w",stdout);
	#endif
	string s;
	while(getline(cin,s)){
		for(int i = 0;i < s.size();++i){
			if(s[i]>='0'&&s[i]<='9'){
				string p="0";
				bool f =0;
				while(i<s.size()&&s[i]>='0'&&s[i]<='9'){
					if(s[i]!='0')f = 1;
					if(f)p.push_back(s[i]);
					++i;
				}
				--i;
				if(p.size()>1){
					for(int i = 1;i < p.size();++i)cout<<p[i];
					cout<<" ";
				}else cout<<p<<" ";
			}
		}
		cout<<endl;
	}
	return 0;
}

B、 牛牛爱位运算

思路

对于数 x x ,它 & 上任何一个数都不会使它变大,所以取个最大值即可。

参考代码

#pragma GCC optimize(2)
#include<bits/stdc++.h>
using namespace std;
const int man = 2e5+10;
#define IOS ios::sync_with_stdio(0)
#define ull unsigned ll
#define uint unsigned
#define pai pair<int,int>
#define pal pair<ll,ll>
#define IT iterator
#define pb push_back
#define fi first
#define se second
#define For(i,j,k) for (int i=(int)(j);i<=(int)(k);++i)
#define Rep(i,j,k) for (int i=(int)(j);i>=(int)(k);--i)
#define endl '\n'
#define ll long long
const ll mod = 1e9+7;

signed main() {
	#ifndef ONLINE_JUDGE
		//freopen("in.txt", "r", stdin);
		//freopen("out.txt","w",stdout);
	#endif
	int t;cin>>t;
	while(t--){
		int n;cin >> n;
		int ans = -1;
		for(int i = 1;i <= n;++i){
			int x;cin >>x;
			ans = max(ans,x);
		}
		cout<<ans<<endl;
	}
	return 0;
}

C、 牛牛爱博弈

思路

模拟一下,可以发现一个规律,以 3 3 为周期,从1开始,赢赢输赢赢输赢赢输。

参考代码

#pragma GCC optimize(2)
#include<bits/stdc++.h>
using namespace std;
const int man = 2e5+10;
#define IOS ios::sync_with_stdio(0)
#define ull unsigned ll
#define uint unsigned
#define pai pair<int,int>
#define pal pair<ll,ll>
#define IT iterator
#define pb push_back
#define fi first
#define se second
#define For(i,j,k) for (int i=(int)(j);i<=(int)(k);++i)
#define Rep(i,j,k) for (int i=(int)(j);i>=(int)(k);--i)
#define endl '\n'
#define ll long long
const ll mod = 1e9+7;

signed main() {
	#ifndef ONLINE_JUDGE
		//freopen("in.txt", "r", stdin);
		//freopen("out.txt","w",stdout);
	#endif
	int t;
	cin >>t;
	while(t--){
		int n;cin >>n;
		bool f = 0;
		n %= 3;
		if(n==0)f = 0;
		else f = 1;
		if(f)cout<<"Alan\n";
		else cout<<"Frame\n";
	}
	return 0;
}

D、 牛妹爱数列

思路

简单 DP, d p [ i ] [ 0 ] dp[i][0] 表示把前 i i 位都变成 0 0 需要的最小代价, d p [ i ] [ 1 ] dp[i][1] 表示把前 i i 位都变成 1 1 需要的最小代价。
转移的方程:
如果 a [ i ] = = 1 a[i]==1 d p [ i ] [ 0 ] = m i n ( d p [ i 1 ] [ 0 ] , d p [ i 1 ] [ 1 ] + 1 ) + 1 ; d p [ i ] [ 1 ] = m i n ( d p [ i 1 ] [ 0 ] + 1 , d p [ i 1 ] [ 1 ] ) ; dp[i][0] = min(dp[i-1][0],dp[i-1][1]+1) + 1; dp[i][1] = min(dp[i-1][0]+1,dp[i-1][1]);
如果 a [ i ] = = 0 a[i]==0 : d p [ i ] [ 0 ] = m i n ( d p [ i 1 ] [ 0 ] , d p [ i 1 ] [ 1 ] + 1 ) ; d p [ i ] [ 1 ] = m i n ( d p [ i 1 ] [ 1 ] , d p [ i 1 ] [ 0 ] ) + 1 ; dp[i][0] = min(dp[i-1][0],dp[i-1][1]+1); dp[i][1] = min(dp[i-1][1],dp[i-1][0]) + 1;

参考代码

#pragma GCC optimize(2)
#include<bits/stdc++.h>
using namespace std;
const int man = 2e5+10;
#define IOS ios::sync_with_stdio(0)
#define ull unsigned ll
#define uint unsigned
#define pai pair<int,int>
#define pal pair<ll,ll>
#define IT iterator
#define pb push_back
#define fi first
#define se second
#define For(i,j,k) for (int i=(int)(j);i<=(int)(k);++i)
#define Rep(i,j,k) for (int i=(int)(j);i>=(int)(k);--i)
#define endl '\n'
#define ll long long
const ll mod = 1e9+7;
int a[man],dp[man][2];

signed main() {
	#ifndef ONLINE_JUDGE
		//freopen("in.txt", "r", stdin);
		//freopen("out.txt","w",stdout);
	#endif
	int n;scanf("%d",&n);
	for(int i = 1;i <= n;++i){
		scanf("%d",&a[i]);
	}
	for(int i = 1;i <= n;++i){
		if(a[i]){
			dp[i][0] = min(dp[i-1][0],dp[i-1][1]+1) + 1;
			dp[i][1] = min(dp[i-1][0]+1,dp[i-1][1]);
		}else{
			dp[i][0] = min(dp[i-1][0],dp[i-1][1]+1);
			dp[i][1] = min(dp[i-1][1],dp[i-1][0]) + 1;
		}
	}
	printf("%d\n",min(dp[n][0],dp[n][1]+1));
	return 0;
}

E、牛妹游历城市

思路

首先暴力建图肯定不行的,直接被卡死。
那么想如何优化。
首先我们可以按位操作,把32位看成点,然后对每个点拆点。
即:对于第 i i 位(二进制) 有两个点, i 1 i_1 (入点)和 i 2 i_2 (出点) , i 1 i_1 i 2 i_2 连一个边,边权为 2 i 2^i
然后对于输入的 a [ i ] a[i] ,如果当前 a [ i ] a[i] 在第 x x 位(二进制)是 1 1 ,那么这个点向 x 1 x_1 连一条边权为 0 0 的边, x 2 x_2 向该点连一条边权为 0 0 的边。
最后跑一遍最短路即可。
正确性:
题目要求的是如果 a i a_i & a j a_j ! = 0 != 0 ,那么这两个点之间可以连边,边权为 l o w b i t ( a i lowbit(a_i & a j ) a_j)
我们这么建图如何保证所走的边的边权是两个点的 l o w b i t ( a i lowbit(a_i & a j ) a_j) 呢。
首先假设存在一条最短路: u u 指向 v v 的,以上建图方式,他们的边权一定是 l o w b i t ( a i lowbit(a_i & a j ) a_j) 吗?答案是肯定的,假设我们最短路已经搜到 u u 这里了,从 u u 开始去找其他的点,它要走到 v v ,那么它下一步的点一定是 u , v u,v 点权二进制位数都有的,且是最低位(符合最短路贪心的思路)。

参考代码

#pragma GCC optimize(2)
#include<bits/stdc++.h>
using namespace std;
const int man = 2e5+10;
#define IOS ios::sync_with_stdio(0)
#define ull unsigned ll
#define uint unsigned
#define pai pair<int,int>
#define pal pair<ll,ll>
#define IT iterator
#define pb push_back
#define fi first
#define se second
#define For(i,j,k) for (int i=(int)(j);i<=(int)(k);++i)
#define Rep(i,j,k) for (int i=(int)(j);i>=(int)(k);--i)
#define endl '\n'
#define ll long long
const ll mod = 1e9+7;
struct node{
	int v;
	ll w;
	bool operator < (const node &a)const{
		return w > a.w;
	}
};
vector<node>sp[man];
ll a[man];

void add(int u,int v,ll w){
	sp[u].push_back(node{v,w});
}
priority_queue<node>q;
ll dis[man];
bool vis[man];int n;
void dij(int s,int num){
	for(int i = 1;i <= num;++i)dis[i] = 1e18,vis[i] = 0;
	dis[s] = 0;
	q.push(node{1,0});
	while(q.size()){
		node tp = q.top();
		q.pop();
		if(vis[tp.v])continue;
		vis[tp.v] = 1;
		for(auto it:sp[tp.v]){
			int v = it.v;
			ll w = it.w;
			if(vis[v])continue;
			if(dis[v]>dis[tp.v] + it.w){
				dis[v] = dis[tp.v] + it.w;
				q.push(node{v,dis[v]});
			}
		}
	}
	if(dis[n]==1e18)printf("Impossible\n");
	else printf("%lld\n",dis[n]);
}


signed main() {
	#ifndef ONLINE_JUDGE
		freopen("in.txt", "r", stdin);
		//freopen("out.txt","w",stdout);
	#endif
	int t;scanf("%d",&t);
	while(t--){
		scanf("%d",&n);
		for(int i = 1;i <= n;++i){
			scanf("%lld",&a[i]);
		}
		int num = n+1;
		for(int i = 0;i <= 32;++i)add(num+i,num+40+i,(1ll<<i));
		for(int i = 1;i <= n;++i){
			for(int j = 0;j <= 32;++j){
				if((a[i]>>j)&1){
					add(i,num+j,0);
					add(num+40+j,i,0);
				}
			}
		}
		dij(1,num+100);
		for(int i = 1;i <= num+100;++i){
		//	cout<<"u:"<<i<<endl;
		//	for(auto it:sp[i])cout<<it.v<<" ";
		//	cout<<endl;
			sp[i].clear();
		}
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/weixin_43571920/article/details/108022159
今日推荐