简单瞎搞题

链接

https://ac.nowcoder.com/acm/contest/5556/E

题目

链接:https://ac.nowcoder.com/acm/contest/5556/E
来源:牛客网

一共有 n个数,第 i 个数是 \(x_i\)
\(x_i\) 可以取 \([l_i , r_i]\) 中任意的一个值。
\(S=∑x_i^2\),求 \(S\) 种类数。
输入描述:
第一行一个数 n。
然后 \(n\) 行,每行两个数表示 \(l_i,r_i\)

输出描述:
输出一行一个数表示答案。
示例
输入
复制

5
1 2
2 3
3 4
4 5
5 6

输出
复制

26

备注:
\(1 ≤ n , l_i , r_i ≤ 100\)

思路

本质问题是一个01背包凑数问题,但是如果枚举物品(区间)个数,物品(区间内的数),背包容量\((1-1000000)\)肯定会超时,所以需要使用bitset优化。

bitset<1000010> bs;

bs[x]=1表示x这个数可以被凑出来,状态转移就是:

bs[i]|=bs[i-1]<<j*j;

表示上一轮凑出来的数左移\(j*j\)位,即上一轮凑出来的数加上\(j*j\),就表示到这一轮可以凑出来的数。
最后bs[n]中1的个数就是可以凑数来数的个数。

代码

#include <iostream>
#include <cstdio>
#include <bitset>
using namespace std;
int n;
bitset<1000010> ans,tmp;
int main() {
    scanf("%d",&n);
    ans[0]=1;
    for(int i=1;i<=n;++i){
    	int l,r;
    	cin>>l>>r;
    	tmp.reset();
    	for(int j=l;j<=r;++j){
    	    tmp|=ans<<(j*j);
	}
	ans=tmp;
    }
    cout<<ans.count()<<endl;
    return 0;
}
posted @ 2020-05-05 22:20  0x4f  阅读(125)  评论(0编辑  收藏  举报