简单瞎搞题
链接
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;
}