JZOJ 5264. 【NOIP2017模拟8.12A组】化学

25 篇文章 0 订阅
12 篇文章 0 订阅

Description

Description

Input

Input

Output

Output

Sample Input

3 10
1 2 10

Sample Output

5

Data Constraint

Data Constraint

Hint

Hint

Solution

  • 看到数据范围( n40 ),就不由自主地想到折半搜索。

  • 于是把 n 先折半,每边 20 ,设两段的总花费分别为 xy ,则显然满足:

    x+ym

  • 前半段 O(220) 枚举每个位置选不选(即顺便算出当前的 x ),

  • 那么后半段的 y 就需要满足:

    ymx

  • 那么我们可以将所有的 x 加入一个数组中,并从小到大排序。

  • 在搜到一个 y 的时候,就在数组中二分查找,直接统计数量即可。

  • 总时间复杂度为 O(2N+N log N)

Code

#include<cstdio>
#include<algorithm>
using namespace std;
typedef long long LL;
const int mo=1e7+7;
int n,n1;
LL m,ans;
LL a[41],f[mo];
inline LL read()
{
    LL X=0,w=1; char ch=0;
    while(ch<'0' || ch>'9') {if(ch=='-') w=-1;ch=getchar();}
    while(ch>='0' && ch<='9') X=(X<<3)+(X<<1)+ch-'0',ch=getchar();
    return X*w;
}
inline void dfs1(int x,LL y)
{
    if(y>m) return;
    if(x>n1)
    {
        f[++f[0]]=y;
        return;
    }
    dfs1(x+1,y+a[x]);
    dfs1(x+1,y);
}
inline void dfs2(int x,LL y)
{
    if(y>m) return;
    if(x>n)
    {
        int l=1,r=f[0];
        while(l<r)
        {
            int mid=(l+r)>>1;
            if(f[mid]<=m-y) l=mid+1; else r=mid;
        }
        if(f[l]>m-y) l--;
        ans+=l;
        return;
    }
    dfs2(x+1,y+a[x]);
    dfs2(x+1,y);
}
int main()
{
    n=read(),m=read(),n1=n>>1;
    for(int i=1;i<=n;i++) a[i]=read();
    dfs1(1,0);
    sort(f+1,f+1+f[0]);
    dfs2(n1+1,0);
    printf("%lld",ans);
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值