#515. 「LibreOJ β Round #2」贪心只能过样例 (简单dp+bitset优化)

版权声明:希望我的博客可以为别人带去知识与便利,让那些像我曾经一样迷茫的小伙伴不再迷茫~ https://blog.csdn.net/qq_34374664/article/details/74622482

题目描述

一共有 nnn个数,第 iii 个数 xix_ixi 可以取 [ai,bi][a_i , b_i][ai,bi] 中任意值。
设 S=∑xi2S = \sum{{x_i}^2}S=xi2,求 SSS 种类数。

输入格式

第一行一个数 nnn
然后 nnn 行,每行两个数表示 ai,bia_i,b_iai,bi

输出格式

输出一行一个数表示答案。

样例

样例输入

5
1 2
2 3
3 4
4 5
5 6

样例输出

26

数据范围与提示

1≤n,ai,bi≤1001 \le n , a_i , b_i \le 1001n,ai,bi100

思路:简单的背包dp,s最大到1e6,每一个数枚举s,f[i][j]=f[i-1][j-k*k](a<=k<=b) 但问题是每次循环需要枚举j,而j的范围显然是[1,100∗100∗i],这样是n5复杂度。。可以用bitset优化,0代表不行,1代表可以,这样就不必枚举s了。。。复杂度并不会算。。。每次只需要左移j*j,代表原来的数都+上j*j,在1哪一位代表哪一位可以组成,不要去想二进制。。

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <bitset>
using namespace std;
bitset<1000005> ans[101];
int main()
{
    int n, l, r;
    scanf("%d", &n);
    ans[0] = 1;
    for(int i = 1; i <= n; i++)
    {
        scanf("%d%d", &l, &r);
        for(int j = l; j <= r; j++)
        {
            ans[i] |= (ans[i-1] << (j*j)); //在前面的所有状态,每个数都+j*j,也就是所有1左移j*j的位置
        }
    }
    printf("%d\n", ans[n].count());
    return 0;
}


展开阅读全文

没有更多推荐了,返回首页