【分组背包】【bitset】简单瞎搞题

https://ac.nowcoder.com/acm/problem/17193
题目描述:
一共有 n个数,第 i 个数是 xi
xi 可以取 [li , ri] 中任意的一个值。
设S= ∑ xi2,求 S 种类数。

输入描述:
第一行一个数 n。
然后 n 行,每行两个数表示 li,ri。

输出描述:
输出一行一个数表示答案。

题意:
相当于是问有一个背包,有n个组,每组选一个数,问最后背包能装的体积有多少种方案。

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

int t,n,m;
bitset<1000100> dp[110];
int l,r;
int main(){
	cin>>n;
	dp[0][0]=1;
	for(int i=1;i<=n;i++){
		cin>>l>>r;
		for(int j=l;j<=r;j++){
			dp[i]|=(dp[i-1]<<(j*j));
		}
	}
	cout<<dp[n].count()<<endl;
	return 0;
}

首先以我现在的能力,肯定是想不到这样的,
但是可以先理解, 慢慢再熟悉。

f[i][j] 为前i个数字能否构成j,考虑第i个数选还是不选。
显然如果f[ i−1 ][ j−x [ i ] 2 ]==1的话 f [ i ][ j ]就是可以的,x [ i ]的取值是 l [ i ]到 r [ i ]。

了解下bitset,
bitset你可以理解为一个长度很长的01数字串(实际上它是用int拼接而成),
也可也理解为可以用位运算的bool数组

用f[i]来表示第i行的01串:f [ i ] = f [ i ] ∣ ( f [ i − 1 ] << ( j 2))
每次往左移 j * j 位 ,然后或等于将重复的舍去了。

展开阅读全文

没有更多推荐了,返回首页

©️2019 CSDN 皮肤主题: 游动-白 设计师: 上身试试
应支付0元
点击重新获取
扫码支付

支付成功即可阅读