HDU6258(2018XTCPC)J - Vertex Cover (组合计数)

题意:
在这里插入图片描述
思路:
考虑如何构造连边使得 B o b o Bobo Bobo当前选择的点是最优的选择,需要一直以维护这个最优为目的来构造。

考虑当前点如果被涂色且序号为 i i i的话,那么表示这个点至少要连出去一条边,为了避免重复计数答案,我们只考虑比 i i i大的 j j j点,即点权值 2 j > 2 i 2^j > 2^i 2j>2i,很明显所有的点权值比当前大的点我都可以和它连边,但是不可以不连,(因为不连边的话,而又要保证当前点是被染色的点,那么就一定要向小的点权节点连边,但是如果这样的话,完全可以不染色 i i i点,就可以达到目的,所以很明这是与之前矛盾的),还有一种特殊情况就是,假如和当前的点 i i i相连的所有 j j j点如果都是被染色的也不行,因为这种连边情况下,我完全没有必要再添加 i i i的点权来达到目的,因为前面的已经够了,与最小的和又矛盾了。

考虑当前的点未被染色的情况,那么很明显如果要连边的话,他一定是和被染色的点连边,否则和未染色的点连,不合法…,而且也可以选择不连。

所以我们从点权值由大到小,维护一下走过了几个点(点权比它大),走过的点中有多少被染色了,组合数统计答案就可以了。

#include <bits/stdc++.h>

using namespace std;

#define pb emplace_back
#define MP make_pair
#define pii pair<int,int>
#define pll pair<ll,ll>
#define lson rt<<1
#define rson rt<<1|1
#define CLOSE std::ios::sync_with_stdio(false)
#define sz(x) (int)(x).size()
typedef long long ll;
typedef double db;
const int INF = 0x3f3f3f3f;
const db eps = 1e-6;
const int N = 1e5 + 10;
const int MOD = 1e9 + 7;

char s[N];
ll n;
int col[N];

ll ksm(ll a,ll b) {
	ll res = 1;
	while(b) {
		if(b & 1) res = res * a % MOD;
		a = a * a % MOD;
		b >>= 1;
	}
	return res % MOD;
}
// 考虑 怎么维护连边 使得给出的这个x染色点是最优的选择 
// 当一条边的两个端点中的任意一个被染色后 这条边就被染色了
int main() {
	while(~scanf("%lld",&n)) {
		scanf("%s",s);
		int len = strlen(s);
		ll tot = n - len;//点权值比我大的点
		ll ans = 1,done = 0;
		for(ll i = 0;i < len;i ++) {
			if(s[i] == '1') {
				ll tmp = ksm(2LL,tot);
				tmp = (tmp - ksm(2LL,done) + MOD) % MOD;
				ans = ans * tmp % MOD;
				done++;
			}
			else ans = ans * ksm(2LL,done) % MOD;
			tot++;
		}
		printf("%lld\n",ans);
	}
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值