[CEOI2015 Day2]世界冰球锦标赛

题目描述

译自 CEOI2015 Day2 T1「Ice Hockey World Championship」

今年的世界冰球锦标赛在捷克举行。\(Bobek\) 已经抵达布拉格,他不是任何团队的粉丝,也没有时间观念。他只是单纯的想去看几场比赛。如果他有足够的钱,他会去看所有的比赛。不幸的是,他的财产十分有限,他决定把所有财产都用来买门票。

给出 \(Bobek\) 的预算和每场比赛的票价,试求:如果总票价不超过预算,他有多少种观赛方案。如果存在以其中一种方案观看某场比赛而另一种方案不观看,则认为这两种方案不同。

输入输出格式

输入格式:

第一行,两个正整数 \(N\) 和 \(M(1 \leq N \leq 40,1 \leq M \leq 10^{18})\),表示比赛的个数和 \(Bobek\) 那家徒四壁的财产。

第二行,\(N\) 个以空格分隔的正整数,均不超过 \(10^{16}\),代表每场比赛门票的价格。

输出格式:

输出一行,表示方案的个数。由于 \(N\) 十分大,注意:答案 \(\le 2^{40}\)。

输入输出样例

输入样例#1:

5 1000
100 1500 500 500 1000

输出样例#1:

8

说明

样例解释

八种方案分别是:

  • 一场都不看,溜了溜了
  • 价格 \(100\) 的比赛
  • 第一场价格 \(500\) 的比赛
  • 第二场价格 \(500\) 的比赛
  • 价格 \(100\) 的比赛和第一场价格 \(500\) 的比赛
  • 价格 \(100\) 的比赛和第二场价格 \(500\) 的比赛
  • 两场价格 \(500\) 的比赛
  • 价格 \(1000\) 的比赛

有十组数据,每通过一组数据你可以获得 \(10\) 分。各组数据的数据范围如下表所示:

数据组号 1-2 3-4 5-7 8-10
$N \leq $ \(10\) \(20\) \(40\) \(40\)
\(M \leq\) \(10^6\) \(10^{18}\) \(10^6\) \(10^{18}\)

题解

首先看数据范围

  1. 1-4组数据\(N\leq20\),爆搜就可以解决。

    inline void dfs(R ll dep,R ll sum){
    if(sum>m)return;
    if(dep==n+1){
    ans++;
    return;
    }
    dfs(dep+1,sum+a[dep]);
    dfs(dep+1,sum);
    }
    int main(){
    read(n);read(m);
    for(R int i=1;i<=n;i++)read(a[i]);
    if(n<=20){
    dfs(1,0);
    printf("%lld\n",ans);
    }
    return 0;
    }
  2. 5-7组数据\(M\leq10^6\),裸的背包啊。

    int main(){
    read(n);read(m);
    for(R int i=1;i<=n;i++)read(a[i]);
    if(m<=1e6){
    f[0]=1;
    for(R int i=1;i<=n;i++)
    for(R int j=m;j>=a[i];j--)
    f[j]+=f[j-a[i]];
    for(R int i=0;i<=m;i++)ans+=f[i];
    printf("%lld\n",ans);
    }
    return 0;
    }
  3. 现在你已经能拿到70分了(但在洛谷上是47分)

下面引出主角——折半搜索(meet in the middle思想)

因为\(N\leq40\) \(O(2^{40})\)的爆搜一定会\(TLE\),所以我们将\(N\)分成两份

搜索\(1\)到\(n/2\)和\(n/2+1\)到\(n\),让复杂度降到\(O(2^{n/2+1})\)。

画一个图(网上找的不错的图)理解一下为什么能降低复杂度

inline void dfs(R int l,R int r,R ll sum,R ll a[],R ll &cnt){
if(sum>m)return;
if(l>r){
a[++cnt]=sum;
return;
}
dfs(l+1,r,sum+w[l],a,cnt);//选
dfs(l+1,r,sum,a,cnt);//不选
}

将前一半的搜索状态存入a数组,后一半存入b数组。

mid=n/2;
dfs(1,mid,0,suma,cnta);
dfs(mid+1,n,0,sumb,cntb);

一般\(meet\) \(in\) \(the\) \(middle\)的难点主要在于最后答案的组合统计。

我们可以现将a或b数组sort,让其有序。

然后通过枚举另一个数组中的状态,来实现统计答案。

上述找\(pos\)的过程可以通过upper_bound()完成。

sort(suma+1,suma+1+cnta);//使一个数组有序
for(R int i=1;i<=cntb;i++)
ans+=upper_bound(suma+1,suma+1+cnta,m-sumb[i])-suma-1;//统计ans

下面是高清完整code:

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cctype>
#define ll long long
#define R register
#define N 55
using namespace std;
template<typename T>inline void read(T &a){
char c=getchar();T x=0,f=1;
while(!isdigit(c)){if(c=='-')f=-1;c=getchar();}
while(isdigit(c)){x=(x<<1)+(x<<3)+c-'0';c=getchar();}
a=f*x;
}
ll n,m,w[N],mid,suma[1<<21],sumb[1<<21],cnta,cntb,ans;
inline void dfs(R int l,R int r,R ll sum,R ll a[],R ll &cnt){
if(sum>m)return;
if(l>r){
a[++cnt]=sum;
return;
}
dfs(l+1,r,sum+w[l],a,cnt);
dfs(l+1,r,sum,a,cnt);
}
int main(){
read(n);read(m);
for(R int i=1;i<=n;i++)read(w[i]);
mid=n>>1;
dfs(1,mid,0,suma,cnta);
dfs(mid+1,n,0,sumb,cntb);
sort(suma+1,suma+1+cnta);
for(R int i=1;i<=cntb;i++)
ans+=upper_bound(suma+1,suma+1+cnta,m-sumb[i])-suma-1;
printf("%lld\n",ans);
return 0;
}

这里还有一道折半搜索的好题,难度升级——luogu,还有 my blog.

【BZOJ4800】[CEOI2015 Day2]世界冰球锦标赛 (折半搜索)的更多相关文章

  1. [luogu4799 CEOI2015 Day2] 世界冰球锦标赛(折半搜索)

    传送门 Solution 折半搜索裸题,注意\(long long\) Code #include <cmath> #include <cstdio> #include < ...

  2. 【题解】P4799[CEOI2015 Day2]世界冰球锦标赛

    [题解][P4799 CEOI2015 Day2]世界冰球锦标赛 发现买票顺序和答案无关,又发现\(n\le40\),又发现从后面往前面买可以通过\(M\)来和从前面往后面买的方案进行联系.可以知道是 ...

  3. [CEOI2015 Day2]世界冰球锦标赛 (双向搜索)

    题目描述 [CEOI2015 Day2]世界冰球锦标赛译自 CEOI2015 Day2 T1「Ice Hockey World Championship」 今年的世界冰球锦标赛在捷克举行.Bobek ...

  4. 题解 P4799 【[CEOI2015 Day2]世界冰球锦标赛】

    题解 P4799 [[CEOI2015 Day2]世界冰球锦标赛] 双向搜索好题 传送门 实际上,双向搜索就是把\(a^n\)的复杂度转变成了大多为\(O(nlogna^{\frac{n}{2}})\ ...

  5. 折半搜索【p4799】[CEOI2015 Day2]世界冰球锦标赛

    Description 今年的世界冰球锦标赛在捷克举行.Bobek 已经抵达布拉格,他不是任何团队的粉丝,也没有时间观念.他只是单纯的想去看几场比赛.如果他有足够的钱,他会去看所有的比赛.不幸的是,他 ...

  6. P4799 [CEOI2015 Day2]世界冰球锦标赛

    \(\color{#0066ff}{题目描述}\) 今年的世界冰球锦标赛在捷克举行.Bobek 已经抵达布拉格,他不是任何团队的粉丝,也没有时间观念.他只是单纯的想去看几场比赛.如果他有足够的钱,他会 ...

  7. P4799 [CEOI2015 Day2]世界冰球锦标赛(折半暴搜)

    题目很明确,不超过预算的方案数.两个直觉:1.暴搜2.dp 每个点两种状态,选或不选.... 1.可过20% 2.可过70% 正解:折半搜索(meet in the middle) 有点像以前的双向广 ...

  8. 洛谷P4799 世界冰球锦标赛 CEOI2015 Day2 meet-in-the-middle

    正解:折半搜索 解题报告: 先放个传送门QAQ 想先说下部分分?因为包含了搜索背包两个方面就觉得顺便复习下?QwQ 第一档部分分 爆搜 就最最普通的爆搜鸭,dfs(第几场,钱),然后每次可以看可以不看 ...

  9. [题解](折半搜索)luogu_P4799_BZOJ_4800世界冰球锦标赛

    抄的题解 以及参考:https://www.cnblogs.com/ZAGER/p/9827160.html 2^40爆搜过不了,考虑折半搜索,难点在于合并左右的答案,因为有可能答案同时载左右两边,我 ...

随机推荐

  1. VS2010调用halcon的时候出现试图加载格式不正确的程序(this.hWindowControl1 = new HalconDotNet.HWindowControl();)

    [重要错误修改] /// <summary> /// 设计器支持所需的方法 - 不要 /// 使用代码编辑器修改此方法的内容. /// </summary> private v ...

  2. 【转载】C# 从服务器下载文件

    支持并尊重原创!原文地址:https://www.cnblogs.com/GoCircle/p/6429136.html 一.//TransmitFile实现下载 protected void But ...

  3. Android Architecture Components

    https://developer.android.com/topic/libraries/architecture/index.html ViewModel 有LiveData Activity 监 ...

  4. jdk环境变量一键设置 管理員运行

    退出360等杀毒软件 本机win10 其他环境自测.参考了网上代码修改. @echo off rem dss color 02 mode con cols=70 lines=30 title JDK ...

  5. AJAX省市县三级联动的实现

    省市县数据 本例子中省市县数据保存在MySQL数据库中,部分数据截图如下: 从数据库中读取数据 导入需要的jar包 连接池配置文件 <c3p0-config> <!-- 默认配置,如 ...

  6. 第01章 开发准备(对最新版的RN进行了升级)1-4 项目底部导航菜单开发

  7. java基础面试题 背过1

    web.xml文件中可以配置哪些内容? 答:web.xml用于配置Web应用的相关信息,如:监听器(listener) ContextLoaderListener .过滤器(filter) Strut ...

  8. 运用alarm系统调用检测网络是否断开

    比如对于一个Server/Client程序,Client会每隔一定时间(比如TIME_OUT_CLIENT)会向Server发送“CheckConnect”信息,Server收到这个信息会调用回调函数 ...

  9. mvc json 日期问题的最简单解决方法

    1.首先编写BaseController这个类,需要引入Newtonsoft.Json.dll程序集 using System;using System.Collections.Generic;usi ...

  10. Servlet中response对象Commit状态的分析

    response是服务端对客户端请求的一个响应,其中封装了响应头.状态码.内容(也就是最终要在浏览器上显示的HTML代码或者其他数据格式)等. 服务端在把response提交到客户端之前,会使用一个缓 ...