JZOJ-senior-3512. 【NOIP2013模拟11.5A组】游戏节目(show)

6 篇文章 0 订阅
5 篇文章 0 订阅

3512. 【NOIP2013模拟11.5A组】游戏节目(show)

(File IO): input:show.in output:show.out
Time Limits: 1000 ms Memory Limits: 262144 KB Detailed Limits

Description

有三支队伍,分别是A,B,C。有n个游戏节目,玩第i个游戏,队伍A可以得到的分数是A[i],队伍B可以得到的分数是B[i],队伍C可以得到的分数是C[i]。由于时间有限,可能不是每个节目都能玩,于是节目主持人决定要从n个游戏节目里面挑选至少k个节目出来(被选中的节目不分次序),使得队伍A成为赢家。队伍A能成为赢家的条件是队伍A的总得分要比队伍B的总得分要高,同时也要比队伍C的总得分要高。节目主持人有多少种不同的选取方案?

Input

第一行,两个整数n和k。

第二行, n个整数,分别是A[1]、A[2]、A[3]…A[n]。

第三行, n个整数,分别是B[1]、B[2]、B[3]…B[n]。

第四行, n个整数,分别是C[1]、C[2]、C[3]…C[n]。

Output

一个整数,表示不同的选取方案数量。

Sample Input

3 2

1 1 2

1 1 1

1 1 1

Sample Output

3

【样例解释】

方案一:选取节目1和节目3。

方案二:选取节目2和节目3。

方案三:选取节目1、节目2、节目3。

Data Constraint

对于40%数据,2 <= n <= 20。

对于100%数据,2 <= n <= 34, 1 <= k <= min(n,7), 1 <=A[i], B[i], C[i]<= 10^9。

题解

分两步处理:
第一步:把问题简单化,假设没有k的限制,设求出来的方案总数是x。
第二步:考虑k的限制,由于k<7,可以穷举n个节目取0个,n个节目取1个,n个节目取2个,n个节目取3个,n个节目取3个,n个节目取4个,n个节目取5个,n个节目取6个,穷举完这几种情况就可以知道哪些方案是合法的。而且Combinations(34,0) + Combinations(34,1) + Combinations(34,2) + Combinations(34,3) + Combinations(34,4) + Combinations(34,5) + Combinations(34,6) = 1676116。
也就是这个穷举不超过1676116次。设第二步的方案总数是y。

那么,最后应该输出的答案就是x - y。

第二步的方案数y可以搜索计算结果,下面重点讲讲第一步的方案数x如何求。
由于n最大是34,直接搜索会超时。可以把n个节目平均分成两部分,即第1至第n/2个节目归为第1部分,第n/2+1个节目至第n个节目归为第2部分。

第1部分:显然最多只有17个节目,每个节目可以取或者不取,穷举这17个节目的所有情况,显然有2^17种取法,对于每一种取法,队伍A都有一个得分,设为scoreA, 队伍B也有一个得分scoreB,队伍C也有一个得分scoreC。不妨设difAB1 = scoreA - scoreB, difAC1 = scoreA - scoreC,即每一种取法,都可以计算出一对值(difAB1,difAC1),

第2部分:显然最多也只有17个节目。每个节目可以取或者不取,穷举这17个节目的所有情况,显然也是有2^17种取法。同理,对于每一种取法,设difAB1 = scoreA - scoreB, difAC1 = scoreA - scoreC,即每一种取法都可以计算出一对值(difAB2,difAC2),

显然,如果一个方案要成立,必须要同时满足:
difAB1 + difAB2 > 0 (即队伍A的总得分比队伍B的总得分高)
difAC1 + difAC2 > 0 (即队伍A的总得分比队伍C的总得分高)

于是,问题转化为,枚举一对值(difAB1,difAC1),在第2部分里面查询有多少对(difAB2,difAC2),使得同时满足
difAB1 + difAB2 > 0
difAC1 + difAC2 > 0

显然,对于第2部分,可以用树状数组或者线段树之类的数据结构进行保存,以备第1部分的查询所需。

由于分两步求答案,于是时间复杂度 = x + y = 2^17 * Log(2^17) + 1676116

Code

#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#define N 40
#define M 150000
#define ll long long
#define fo(i,a,b) for(i=a;i<=b;i++)
using namespace std;
ll i,j,n,k,s,t1,t2,ans1,ans2;
ll a[N],b[N],c[N],tr[4*M];
ll ab1[M],ac1[M],ab2[M],ac2[M];
struct node{ll x,y,z;}d[2*M];
void dg(ll w,ll l,ll x,ll y,ll z)
{
    if (w>i) {if (x>y && x>z) ans1++; return;}
    for(ll j=l+1; j<=n; j++) dg(w+1,j,x+a[j],y+b[j],z+c[j]);
}
void dfs1(ll l,ll x,ll y,ll z)
{
    t1++,ab1[t1]=x-y,ac1[t1]=x-z;
    for(ll j=l+1; j<=n/2; j++) dfs1(j,x+a[j],y+b[j],z+c[j]);
}
void dfs2(ll l,ll x,ll y,ll z)
{
    t2++,ab2[t2]=y-x,ac2[t2]=z-x;
    for(ll j=l+1; j<=n; j++) dfs2(j,x+a[j],y+b[j],z+c[j]);
}
bool cmd(node p,node q)
{
    return p.y<q.y;
}
bool cmp(node p,node q)
{
    return p.x<q.x || p.x==q.x && p.y<q.y;
}
void find(ll x,ll st,ll en,ll l,ll r)
{
    if (l>r) return;
    if (st==l && en==r) {s+=tr[x]; return;}
    ll m=(st+en)>>1;
    if (r<=m) find(x+x,st,m,l,r);
    else if (l>m) find(x+x+1,m+1,en,l,r);
    else find(x+x,st,m,l,m),find(x+x+1,m+1,en,m+1,r);
}
void change(ll x,ll l,ll r,ll p)
{
    if (l==r) {tr[x]++; return;}
    ll m=(l+r)>>1;
    if (p<=m) change(x+x,l,m,p);
    else change(x+x+1,m+1,r,p);
    tr[x]=tr[x+x]+tr[x+x+1];
}
int main()
{
    freopen("show.in","r",stdin);
    freopen("show.out","w",stdout);
    scanf("%lld%lld",&n,&k);
    fo(i,1,n) scanf("%lld",&a[i]);
    fo(i,1,n) scanf("%lld",&b[i]);
    fo(i,1,n) scanf("%lld",&c[i]);
    fo(i,1,k-1) dg(1,0,0,0,0);
    dfs1(0,0,0,0);
    dfs2(n/2,0,0,0);
    fo(i,1,t1) d[i].x=ab1[i],d[i].y=ac1[i],d[i].z=1;
    fo(i,1,t2) d[i+t1].x=ab2[i],d[i+t1].y=ac2[i],d[i+t1].z=2;
    sort(d+1,d+1+t1+t2,cmd);
    ll e=1,l=1;
    d[t1+t2+1].y=-2147483647;
    fo(i,2,t1+t2+1) if (d[i].y!=d[i-1].y)
    {
        fo(j,l,i-1) d[j].y=e;
        e++,l=i;
    }
    e--;
    sort(d+1,d+1+t1+t2,cmp);
    ll g,o=0;
    while (o<=t1+t2)
    {
        g=d[o].x,l=o;
        while (d[o].x==g && o<=t1+t2) o++;
        fo(i,l,o-1) if (d[i].z==1) s=0,find(1,1,e,1,d[i].y-1),ans2+=s;
        fo(i,l,o-1) if (d[i].z==2) change(1,1,e,d[i].y);
    }
    printf("%lld",ans2-ans1);
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
本项目是一个基于SpringBoot开发的华府便利店信息管理系统,使用了Vue和MySQL作为前端框架和数据库。该系统主要针对计算机相关专业的正在做毕设的学生和需要项目实战练习的Java学习者,包含项目源码、数据库脚本、项目说明等,有论文参考,可以直接作为毕设使用。 后台框架采用SpringBoot,数据库使用MySQL,开发环境为JDK、IDEA、Tomcat。项目经过严格调试,确保可以运行。如果基础还行,可以在代码基础之上进行改动以实现更多功能。 该系统的功能主要包括商品管理、订单管理、用户管理等模块。在商品管理模块中,可以添加、修改、删除商品信息;在订单管理模块中,可以查看订单详情、处理订单状态;在用户管理模块中,可以注册、登录、修改个人信息等。此外,系统还提供了数据统计功能,可以对销售数据进行统计和分析。 技术实现方面,前端采用Vue框架进行开发,后端使用SpringBoot框架搭建服务端应用。数据库采用MySQL进行数据存储和管理。整个系统通过前后端分离的方式实现,提高了系统的可维护性和可扩展性。同时,系统还采用了一些流行的技术和工具,如MyBatis、JPA等进行数据访问和操作,以及Maven进行项目管理和构建。 总之,本系统是一个基于SpringBoot开发的华府便利店信息管理系统,使用了Vue和MySQL作为前端框架和数据库。系统经过严格调试,确保可以运行。如果基础还行,可以在代码基础之上进行改动以实现更多功能。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值