1956: #515. 「LibreOJ β Round #2」贪心只能过样例
Time Limit: 5 Sec Memory Limit: 128 MBSubmit: 11 Solved: 6
[ Submit][ Status][ Web Board]
Description
一共有 n个数,第 i 个数 xi 可以取 [ai,bi] 中任意值。
设 S=∑xi2,求 S 种类数。
Input
第一行一个数 n。
然后 n 行,每行两个数表示 ai,bi。
Output
输出一行一个数表示答案。
Sample Input
5
1 2
2 3
3 4
4 5
5 6
Sample Output
26
HINT
因oj不支持markdown和tex.
若无法正确显示tex数学公式,请使用google chrome浏览器并安装math anywhere插件(**谁改了题面啊**。药丸.jpg
【分析】
f[i][j]表示前i个数能否组成j,那么对于当前存在的第i个区间[l,r],考虑所有存在的f[i-1][j]==1都可以推到f[i][j+k*k];
换种写法就是f[i][j]=f[i-1][j-k*k](l<=k<=r),但是考虑数据范围虽然只有100,但是最终结果最大会有1000000,也就是说f数组的定义需要f[100][1000000],那么算法复杂度为O(n^5),那么显然是TLE的...但是考虑到f数组中只存0/1表示是否可行,那么就可以用bitset优化一下,
对当前的f[i]可能情况,只要左移k*k位,就是能组成的新情况,然后所有结果取or结果就可以了
//然后这里有一个小优化,因为数据范围有100*100*100*100,这里用滚动数组的方式可以优化内存,当然对这道题目没有影响....
【代码】
#include <iostream>
#include <cstring>
#include <cmath>
#include <cstdio>
#include <bitset>
using namespace std;
bitset<1001000>a,b;
int main()
{
int n;
while (~scanf("%d",&n))
{
a.reset();a[0]=1;
while (n--)
{
int x,y;scanf("%d%d",&x,&y);
b.reset();a<<=(x*x);b|=a;
for (int i=x+1;i<=y;i++)
{
a<<=(i*i-(i-1)*(i-1));
b|=a;
}
a=b;
}
printf("%d\n",a.count());
}
return 0;
}