牛客挑战赛53题解

A题

题意:进行最少操作从原点走到x处,第k次操作可以选择向右走k步或者向左走1步。

解:先用最少的次数到达>=x,即求出最小的r,r*(r+1)/2 >= x,

此时,可能多走了0-(r-2)步,

考虑在前面的操作中选择一个变成往左走。

比如第1步往左走,最终对答案的影响是-2,以此类推,第i步变成往左走会让答案-(i+1),所以除非r*(r+1)/2 - x == 1,其余的x都可以在r步得到。

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

typedef long long ll;
ll x;
int t;

int main()
{
	std::ios::sync_with_stdio(false);
	cin.tie(0); cout.tie(0);
	cin>>t;
	while(t--)
	{
		cin>>x;
		ll k = 1LL * (long long)sqrt(x * 2);
		if(k * (k + 1) / 2 < x) k++;
		ll r = k * (k + 1) / 2 - x;
		if(r == 1) k++;
		cout<<k<<'\n';
	}
	return 0;
}

B题

题意:给出s,要求构造一个只包含0,1和质数的序列使得序列的和为s,要求序列长度尽可能小。

解:先来背诵哥德巴赫猜想qaq。

如果本身这个数不是质数。

根据关于偶数的哥德巴赫猜想,任意一个大于2的偶数都可以写成两个素数之和。

然后对于奇数x来说,有两种思路,变成2+(x-2),这样序列就有最多2个数,只需要检查x-2是不是质数就可以,或者变成1+(x-1),因为x-1是偶数,所以序列最多3个数。

因为n只有1e7,预处理出质数暴力查找即可。

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

const int N = 1e7;
int p[N + 10];
bool vis[N + 10];
int tot,t,n;

void init()
{
	for(int i = 2;i <= N; ++i)
	{
		if(!vis[i]) p[++tot] = i;
		for(int j = 1;j <= tot && p[j] * i <= N; ++j)
		{
			vis[i * p[j]] = 1;
			if(i % p[j] == 0) break;
		}
	}
}

int main()
{
	std::ios::sync_with_stdio(false);
	cin.tie(0); cout.tie(0);
	init();
	cin>>t;
	while(t--)
	{
		cin>>n;
		if(n <= 2 || !vis[n])
		{
			cout<<"1\n"<<n<<" = "<<n<<'\n';
			continue;
		}
		if(n % 2 == 0)
		{
			for(int i = 1;i <= tot && p[i] <= n; ++i)
				if(!vis[n - p[i]])
				{
					cout<<"2\n"<<p[i]<<" + "<<n - p[i]<<" = "<<n<<'\n';
					break;
				}
            continue;
		}
		if(!vis[n - 2]) 
        {
            cout<<"2\n2 + "<<n - 2<<" = "<<n<<'\n';
            continue;
        }
		for(int i = 1;i <= tot && p[i] <= n - 1; ++i)
			if(!vis[n - p[i] - 1])
			{
				cout<<"3\n1 + "<<p[i]<<" + "<<n - p[i] - 1<<" = "<<n<<'\n';
				break;
			}
	}
	return 0;
}

C题

题意:给出n个点m条边的无向图,求每个集合中有多少个子集是独立集(独立集是指集合中任意两点之间都没有边)。

解:n只有26。dp[i]表示编号为i的集合中有多少子集是独立集,我们设x为i的二进制为1的最低位(即lowbit(i))。

如果选择x不冲突,dp[i]可以由dp[i^(1<<x)]转移过来,

如果选择x冲突,dp[i]可以由dp[i^(i & pw[x)]转移过来,pw记录的是所有x的互斥的点。

最后,又卡时间又卡空间太难受了,被迫写的特别丑才过,复杂度是O(2^n)

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

typedef long long ll;
const int p = 1e9 + 7;
int pw[26];
int dp[(1 << 26) + 10];
int pe[(1 << 25) + 10];
int n,m,x,y;

int main()
{
	std::ios::sync_with_stdio(false);
	cin.tie(0); cout.tie(0);
	cin>>n>>m;
	for(int i = 0;i < n; ++i) 
        pw[i] = (1 << i),pe[(1 << i)] = i;
	while(m--)
	{
		cin>>x>>y;
		pw[x] |= (1 << y);
		pw[y] |= (1 << x);
	}
	dp[0] = 1;
	for(int i = 1;i < (1 << n); ++i)
	{
		int id = pe[i&(-i)];
		dp[i] = dp[i ^ (1 << id)] + dp[i ^ (i & pw[id])];
        if(dp[i] >= p) dp[i] -= p;
	}
    ll ans = 0;
    for(int i = (1 << n) - 1;i >= 0; --i) 
        ans = (233LL * ans + dp[i]) % p;
	cout<<ans<<'\n';
	return 0;
}
全部评论

相关推荐

和蔼:在竞争中脱颖而出,厉害! 但是有一个小问题:谁问你了?😡我的意思是,谁在意?我告诉你,根本没人问你,在我们之中0人问了你,我把所有问你的人都请来 party 了,到场人数是0个人,誰问你了?WHO ASKED?谁问汝矣?誰があなたに聞きましたか?누가 물어봤어?我爬上了珠穆朗玛峰也没找到谁问你了,我刚刚潜入了世界上最大的射电望远镜也没开到那个问你的人的盒,在找到谁问你之前我连癌症的解药都发明了出来,我开了最大距离渲染也没找到谁问你了我活在这个被辐射蹂躏了多年的破碎世界的坟墓里目睹全球核战争把人类文明毁灭也没见到谁问你了
点赞 评论 收藏
分享
10-28 15:45
门头沟学院 C++
西南山:海康威视之前不是大规模裁员吗
点赞 评论 收藏
分享
点赞 收藏 评论
分享
牛客网
牛客企业服务