牛客小白赛40题解

A题

题意:一个数字x,问最少操作多少次变成0,操作如下:

二进制下1的个数是奇数,最低位取反,否则最高位取反

解:按照题意模拟一下就可以。

因为2次操作都至少会去掉一个最高位,所以次数一定不会很多

每次统计一下二进制下1出现的次数,奇数就异或1(最低位),偶数就异或最高位即可啦~~

ps:懒得写快读也过了

#include<bits/stdc++.h>
using namespace std;

typedef long long ll;
ll x;
int t,ans;

int main()
{
	std::ios::sync_with_stdio(false);
	cin.tie(0); cout.tie(0);
	cin>>t;
	while(t--)
	{
		ans = 0;
		while(x)
		{
			ans++;
			ll k = x;
			int s = 0,r = 0;
			while(k)
			{
				r++;
				if(k & 1) s++;
				k /= 2;
			}
			if(s & 1) x ^= 1;
			else x ^= (1ll << (r - 1));
		}
		cout<<ans<<'\n';
	}
	return 0;
}

B题

题意:

解:

C题

D题

题意:通过插入字符使得给出的串的相邻字母不相同,问最后串的长度最小是多少

解:如果原串中两相邻字母相同,就势必要插入一个字母,从前往后扫描一遍,统计有多少对这样的相邻字母即可。

#include <bits/stdc++.h>
using namespace std;

const int N = 1e5 + 10;
int n,t;
char a[N];

int main()
{
	scanf("%d",&t);
	while(t--)
	{
		int ans;
		scanf("%s",a);
		n = strlen(a);
		ans = n;
		for(int i = 1;i < n; ++i)
			if(a[i] == a[i - 1]) ans++;
		printf("%d\n",ans);
	}
	return 0;
}

E题

题意:给出n个数,要求分成m组,每一组必须包含相同的数字,问人数最多的组最少多少人?

解:最大值最小化,很明显的二分答案求解。

二分人数最多的组有x人,暴力check,

求所有组都不超过x人,能够分成多少组,如果<=m组,那么答案可行,否则不可行

#include<bits/stdc++.h>
using namespace std;

typedef long long ll;
int t,ans,l,r,n,m,x;
map<int,int>q;

bool check(int x)
{
	int s = 0;
	for(auto k: q)
		s += k.second / x + (k.second % x != 0);
	return s <= m;
}

int main()
{
	std::ios::sync_with_stdio(false);
	cin.tie(0); cout.tie(0);
	cin>>n>>m;
	for(int i = 1;i <= n; ++i) cin>>x,q[x]++;
	int l = 1,r = n;
	int ans = n + 1;
	while(l <= r)
	{
		int mid = (l + r) / 2;
		if(check(mid)) ans = min(ans,mid),r = mid - 1;
		else l = mid + 1;
	}
	if(ans == n + 1) cout<<"-1\n";
    else cout<<ans<<'\n';
	return 0;
}

F题

G题

题意:有n个人,每个人都有一个期望温度,当室内温度与期望温度差的绝对值不超过p,他就会很舒服,最多能有多少人感到舒服。

解:这题比较基础,支持区间修改和最大值查询的数据结构都可以做

我是差分做的,每个人感到舒服的都是一个区间,我们统计所有区间,在某个温度下,有多少线段覆盖就表示有多少人感到舒服。

#include <bits/stdc++.h>
using namespace std;

const int N = 3e6 + 10;
int n,t,p;
int a[N];
int s,ans;

int main()
{
	cin>>n>>p;
	for(int i = 1;i <= n; ++i)
	{
		int x;
		cin>>x;
		a[x]++,a[x + 2 * p + 1]--,s = max(s,x);
	}
	for(int i = 1;i <= s + 2 * p; ++i)
		a[i] += a[i - 1],ans = max(ans,a[i]);
	cout<<ans<<'\n';
	return 0;
}

I题

题意:需要给n个人排队,每个人有一个a[i],代表第i个人希望排在a[i]前面,问有多少种排队方式满足所有人。

解:一定一定要注意数据范围,n<=10,直接全排列判断是否符合条件即可。

10!=362800

#include<bits/stdc++.h>
using namespace std;

int a[12],b[12];
int ans,n;

int main()
{
	std::ios::sync_with_stdio(false);
	cin.tie(0); cout.tie(0);
	cin>>n;
	for(int i = 1;i <= n; ++i) cin>>a[i];
	for(int i = 1;i <= n; ++i) b[i] = i;
	int ans = 0;
	do{
		int flag = 1;
		for(int i = 1;i <= n; ++i)
			for(int j = 1;j <= n; ++j)
			{
				if(b[j] == a[i]) break;
				if(b[j] == i) flag = 0;
			}
		if(flag) ans++;
	}while(next_permutation(b + 1,b + n + 1));
	cout<<ans<<'\n';
	return 0;
}
全部评论

相关推荐

点赞 收藏 评论
分享
牛客网
牛客企业服务