牛客练习赛22-C简单瞎搞题(bitset优化dp)

题目链接:https://www.nowcoder.com/acm/contest/132/C


题目描述

一共有 n个数,第 i 个数是 x i  x i   可以取 [l i , r i ] 中任意的一个值。
 
,求 S 种类数。0 <=n, li, ri <= 100。

输入

5
1 2
2 3
3 4
4 5
5 6

输出

26

题目大意:给你几段序列的初始值和结束值,每段序列任取一个值,设S为取值的平方和,si为S的取值集合,问si的大小。


分析:用bitset来做,(bitset讲解链接:https://blog.csdn.net/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;
}

 
 

猜你喜欢

转载自blog.csdn.net/godjing007/article/details/81044243