北京集训DAY5
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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){;}
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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) {;}
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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 }
作者:乌鸦坐飞机
出处:http://www.cnblogs.com/whistle13326/
新的风暴已经出现
怎么能够停止不前
穿越时空 竭尽全力
我会来到你身边
微笑面对危险
梦想成真不会遥远
鼓起勇气 坚定向前
奇迹一定会出现