2018湖南湘潭CCPC邀请赛 && HDU6285: J. Vertex Cover(计数)

博客围绕Vertex Cover问题展开,介绍了该问题的时间、内存限制及输入输出要求。题意是给定n个点的完全图,已知点集求满足条件的边集数量。解题思路是从代价最高的点往低枚举,根据点是否被选确定方案数,最后连乘得到最终答案。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

 

Vertex Cover

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 196    Accepted Submission(s): 69

Problem Description

Alice and Bobo are playing a game on a graph with n vertices numbered with 0,1,…,(n−1).
The vertex numbered with i is associated with weight 2i.
The game is played as follows.
Firstly, Alice chooses a (possibly empty) subset of the n(n−1)2 edges.
Subsequently Bobo chooses a (possibly empty) subset of the n vertices to *cover* the edges chosen by Alice.
An edge is *covered* if one of its two ends is chosen by Bobo.
As Bobo is smart, he will choose a subset of vertices whose sum of weights, denoted as S, is minimum.
Alice would like to know the number of subsets of edges where Bobo will choose a subset whose sum of weights is exactly k (i.e. S=k), modulo (109+7).

Input

The input consists of several test cases and is terminated by end-of-file.
Each test case contains two integers n and k.
For convenience, the number k is given in its binary notation

Output

For each test case, print an integer which denotes the result.
## Constraint
* 1≤n≤105
* 0≤k<2n
* The sum of n does not exceed 250,000.

Sample Input

3 1 4 101 10 101010101

Sample Output

3 12 239344570

 

 

题意:

给你n个点的完全图(任意两点都有边),选择第i个点的代价为\small 2^{i-1},现在给你一个边集和点集,已经知道边集中的每一条边都有至少一个端点在点集中,并且这个点集是在满足前一个条件的多个点集中代价最小的,然而你遗忘了边集, 现在给你点集,问有多少种边集满足条件(显然点集共有\small 2^n种情况,边集共有\small 2^{\frac{n(n-1)}{2}}种情况)

 

思路:

从代价最高的点开始往代价低的点枚举

  1. 如果当前点被选了,那么一定存在至少一个代价比它高没有被选的点和它相连,方案数为\small 2^p-2^q
  2. 如当前点没被选,那么他可能和所有代价比它高的点有连接,方案数为\small 2^q
  3. 其中p表示代价比当前高的点的数量,q表示代价比当前点高且被选中的点的数量

然后只要连乘就是最终答案了

 

#include<stdio.h>
#include<string.h>
#define LL long long
#define mod 1000000007
char str[100005];
LL er[100005] = {1};
int main(void)
{
	LL now, ans;
	int n, i, len, m, sum;
	for(i=1;i<=100002;i++)
		er[i] = er[i-1]*2%mod;
	while(scanf("%d%s", &n, str+1)!=EOF)
	{
		m = strlen(str+1);
		len = n-m;
		ans = 1, sum = 0;
		for(i=1;i<=m;i++)
		{
			now = 1;
			if(str[i]=='1')
			{
				now = er[len];
				now = (now-er[sum]+mod)%mod;
				sum++;
			}
			else
				now = er[sum];
			len++;
			ans = (ans*now)%mod;
		}
		printf("%lld\n", ans);
	}
	return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值