题目链接:https://www.nowcoder.com/acm/contest/132/C
题目描述
一共有 n个数,第 i 个数是 x
i
x
i
可以取 [l
i
, r
i
] 中任意的一个值。

输入
5 1 2 2 3 3 4 4 5 5 6
输出
26
题目大意:给你几段序列的初始值和结束值,每段序列任取一个值,设S为取值的平方和,si为S的取值集合,问si的大小。
分析:用bitset来做,(bitset讲解链接:https://blog.youkuaiyun.com/GodJing007/article/details/81044000) 用bitset数组f[i]存结果,对于每一个f[I][j], 代表当加了I个序列,值为j的数有没有在si集合中。
状态转移方程:
f[I] |= f[I-1] << num*num;
为什么用bitset呢?因为bitset中的异或,左移 可以方便的又高效的表示集合取并集,平方的相加。显著降低时间复杂度。
代码如下:
#include<bits/stdc++.h>
using namespace std;
const int N=105;
bitset<1000005>f[N];
int main()
{
int n,l,r;
cin>>n;
f[0][0]=1; //表示没加序列时,0在si中。
for(int i=1;i<=n;i++)
{
cin>>l>>r;
for(int j=l;j<=r;j++)
f[i]|=f[i-1]<<j*j; //f[I-1]<<j*j表示再加一个序列取值的平方,f[I]|=f[I-1]表示将每种结果合并到si中。
}
cout<<f[n].count(); //最后输出si集合的大小,即最终有几种可能取值。
return 0;
}