北京集训DAY5

 1 /*
 2     首先我们知道 2的连续的整数次幂可以构成连续的一段区间
 3     例如 1 2 4 可以用来表示 1-7 
 4     如果想要表示8的话 第四个数只能为8 如果大于8 那么8则无法表示
 5     
 6     本题同理 我们假设 前k个数可以表示 1-sum 则sum为前k个数的前缀和
 7     如果第k+1个数大于sum 在无法表示sum+1 
 8     输出即可 
 9 */
10 #include <cstdio>
11 #include <cctype>
12 #include <iostream>
13 #include <algorithm>
14 
15 using namespace std;
16 
17 typedef long long LL; 
18 
19 const int N=1e5+5;
20 
21 int n,a[N];
22 
23 LL sum;
24 
25 bool flag;
26 
27 inline void read(int&x) {
28     int f=1;register char c=getchar();
29     for(x=0;!isdigit(c);c=='-'&&(f=-1),c=getchar());
30     for(;isdigit(c);x=x*10+c-48,c=getchar());
31     x=x*f;
32 }
33 
34 int hh() {
35     freopen("lost.in","r",stdin);
36     freopen("lost.out","w",stdout);
37     read(n);
38     for(int i=1;i<=n;++i) read(a[i]);
39     std::sort(a+1,a+n+1);
40     for(int i=1;i<=n;++i) {
41         if(a[i]>sum+1) {
42             cout<<sum+1<<endl;
43             flag=true;
44             break;
45         } 
46         else sum+=(LL)a[i];
47     }
48     if(!flag) cout<<sum+1<<endl;
49     return 0;
50 }
51 
52 int sb=hh();
53 int main(int argc,char**argv){;}
代码

 

 1 /*
 2     对于前60的数据 利用除法分块可以轻松跑过
 3     复杂度为 O(srqt(n)) 
 4     但是对于1e18 复杂度达到 1e9 除法分块就不行了 
 5     
 6     我们可以先打一个表 看看有没有规律 
 7     据说是有一个O(1) 出解的规律 但是我没有看出来。
 8     所以用的另一个规律 先二分 再判断ans 
 9 */
10 #include <cctype>
11 #include <cstdio>
12 #include <iostream>
13 
14 using namespace std;
15 
16 typedef unsigned long long LL;
17 
18 LL n,ans;
19 
20 int hh() {
21     freopen("div.in","r",stdin);
22     freopen("div.out","w",stdout);
23     cin>>n;
24     LL l=0,r=1000000000;
25     while(l+1<r) {
26         LL mid=(l+r)>>1;
27         if(((mid*mid)+mid)-1>=n) r=mid;
28         else l=mid;
29     }
30     LL p=r-1;
31     LL sum=(p*p)+p-1+r;
32     if(n<=sum) ans=r*2-2;
33     else ans=r*2-1;
34     cout<<ans<<endl;
35     fclose(stdin);
36     fclose(stdout);
37     return 0;
38 }
39 
40 int sb=hh();
41 int main(int argc,char**argv) {;}
代码

 

 

 1 /*
 2     没有意识到这题的复杂度 是2^n 
 3     所以打了一个 最裸的暴力拿了60 (其实 看到数据范围我也打不出正解)
 4     
 5     正解是一种不太常用的思想 
 6     叫做 meet in middle 
 7     对于极限数据 n<=30 
 8     2^30 接近于1e9 这是无法跑出来的
 9     所以利用 meet in middle
10     把搜索分成两部分 前一部分 只搜前2^15种状态
11     后一部分搜 后2^15种状态  然后两部分合并
12     总复杂度 O(2*2^(n/2))  
13 */
14 #include<cstdio>
15 #include<cstring>
16 #include<algorithm>
17 #include<vector>
18 
19 using namespace std;
20 
21 int tt;
22 
23 int n,m;
24 
25 int v[35];
26 
27 double p[35];
28 
29 double ans[35];
30 
31 vector<pair<int,double> > sta[35];
32 
33 int main(){
34     freopen("diamond.in","r",stdin);
35     freopen("diamond.out","w",stdout);
36     scanf("%d%d",&n,&m);
37     for(int i=1,x;i<=n;i++){
38         scanf("%d%d",&v[i],&x);
39         p[i]=x/100.;
40     }
41     for(int i=0;i<=n;i++) sta[i].clear();
42     int an=(n/2.5)+1;
43     int bn=n-an;
44     for(int st=0;st<1<<bn;st++){
45         double nowp=1;
46         int cnt=0,money=0;
47         for(int i=0;i<bn;i++){
48             if((st>>i)&1){
49                 money+=v[n-i];
50                 nowp*=p[n-i];
51             }
52             else
53                 cnt++,nowp*=(1-p[n-i]);
54         }
55         sta[cnt].push_back(make_pair(money,nowp));
56     }
57     for(int i=0;i<=n;i++){
58         sort(sta[i].begin(),sta[i].end());
59         for(int j=1;j<sta[i].size();j++) sta[i][j].second+=sta[i][j-1].second;
60     }
61     for(int st=0;st<1<<an;st++){
62         double nowp=1;
63         int cnt=0,money=0;
64         for(int i=0;i<an;i++){
65             if((st>>i)&1){
66                 money+=v[i+1];
67                 nowp*=p[i+1];
68             }
69             else cnt++,nowp*=(1-p[i+1]);
70         }
71         for(int i=0;i<=bn;i++){
72             int L = m-money;
73             vector<pair<int,double> >::iterator it = lower_bound(sta[i].begin(),sta[i].end(),make_pair(L,-1.));
74             double tmp = sta[i].back().second;
75             if(it!= sta[i].begin()){
76                 it--;
77                 tmp-=it->second;
78             }
79             ans[cnt+i] += tmp*nowp;
80         }
81     }
82     for(int i=0;i<=n;i++) printf("%.3f\n",ans[i]);
83      fclose(stdout);
84     return 0;
85 }
代码

 

posted @ 2017-10-11 07:59  拿叉插猹哈  阅读(268)  评论(33编辑  收藏  举报