这个题目还有点意思。。。一开始愣是没看懂。。。暴力的做法O(100^100)超时,因为最终要是求得所有不同数的个数,我们考虑用二进制表示这个数能出现或者不能出现。二进制操作有一个非常好用的工具是bitset。如果不会bitset,http://www.cplusplus.com/reference/bitset/bitset/。因为数字最大无非是,,所以bitset开到1e6就行了,bitset从右边往左边走,它的位置表示十进制位置。感觉说不太清,直接举例子吧。
如果输入
2
1 2
1 2
先考虑,我们有,
看一下二进制是如何操作的。
图片说明
给定表示二进制串向左移动个位置,这个位置刚好就是i所对应的十进制数,一开始设,表示答案串最后一位为1没有实际意义就是为了后面的操作。然后,这个时候字符串下标1的位置字符串0变1(|有1则1),然后,这个时候字符串4的位置0变1,看到这里应该明白了,01二进制串第表示这个数不会出现,为表示这个数出现,并且下标就是对应这个数的值。我们再来考虑,看它是怎么累加的。结束后我们要保存这个结果串,然后继续遍历,这个时候,s1已经是上一个区间数的串了,在这个基础上继续左移,,当
图片说明
注意到,表示的就是(对应下标看)。然后还有,就是最后一个串,因为我们只要求出现一次的数,出现多次的会被运算覆盖掉,然后不断迭代,最后答案串的的个数就是的种类数。
代码:

#include<iostream>
#include<bitset> 
using namespace std;

const int maxn = 1100000 ;
void solved(){
    int n;cin>>n;
    bitset<maxn>s1,s2;
    s1.set(0);
    while(n--){
        s2.reset(); 
        int l,r;cin>>l>>r;
        for(int i = l ; i <= r; i++){
            s2 |= s1 << (i * i);
        }
        s1 = s2;
    }
    cout<<(int)s1.count()<<endl;
}
int main(){
    solved();
    return 0;
}