牛客算法周周练5

链接:https://ac.nowcoder.com/acm/contest/5556/E
来源:牛客网

时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 32768K,其他语言65536K
64bit IO Format: %lld

题目描述

一共有 n个数,第 i 个数是 xi 
xi 可以取 [li , ri] 中任意的一个值。
设S=∑xi2,求S的种类数。

输入描述:

第一行一个数 n。 
然后 n 行,每行两个数表示 li,ri。 

输出描述:

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

示例1

输入

5
1 2
2 3
3 4
4 5
5 6

输出

26

备注:

1 ≤ n , li, ri ≤ 100

不了解bitset的先看看这个:

https://www.cnblogs.com/magisk/p/8809922.html

题解:

这题用bitset来优化动态规划

bitset其实就相当于我们平时使用的vis[]数组,bitset中的某一位是1就相当于vis[]=true

bitset数组ans表示最后所有结果的集合,为什么要用bitset呢?因为在bitset中可以使用异或、左移,可以方便快速的进行集合取并集,和数的相加,可以显著降低时间复杂度。

状态转移方程:temp |= ans<<(x*x)


注意:

bitset中每一位的下标和我们看二进制数时是相反的

二进制数1101存到bitset中是{1,0,1,1},根据bitset的size补齐0

bitset中使用<<和>>时想象成对这个bitset数组代表的二进制数进行操作就行了

 1 #include <bits/stdc++.h>
 2 #include <bitset>//用bitset要加这个头文件
 3 typedef long long LL;
 4 #define pb push_back
 5 const int INF = 0x3f3f3f3f;
 6 const double eps = 1e-8;
 7 const int mod = 1e9+7;
 8 const int maxn = 1e5+10;
 9 using namespace std;
10 
11 bitset<1000005> ans,temp;
12 
13 int main()
14 {
15     #ifdef DEBUG
16     freopen("sample.txt","r",stdin); //freopen("data.out", "w", stdout);
17     #endif
18     
19     int n;
20     scanf("%d",&n);
21     ans.set(0); //为了后面更新值,最初让0在ans集合中
22     for(int i=1;i<=n;i++)
23     {
24         int l,r;
25         scanf("%d %d",&l,&r);
26         temp.reset();//让temp所有位都为0
27         for(int j=l;j<=r;j++)
28             temp |= ans << (j*j);
29         ans=temp;
30     }
31     printf("%d
",ans.count());//输出ans中位上是1的个数
32     
33     return 0;
34 }

-

原文地址:https://www.cnblogs.com/jiamian/p/12833703.html