1. 程式人生 > >4800: [Ceoi2015]Ice Hockey World Championship(折半搜尋)

4800: [Ceoi2015]Ice Hockey World Championship(折半搜尋)

4800: [Ceoi2015]Ice Hockey World Championship

Time Limit: 10 Sec  Memory Limit: 256 MB
Submit: 622  Solved: 311
[Submit][Status][Discuss]

Description

有n個物品,m塊錢,給定每個物品的價格,求買物品的方案數。  

 

Input

第一行兩個數n,m代表物品數量及錢數 第二行n個數,代表每個物品的價格
n<=40,m<=10^18  

 

Output

一行一個數表示購買的方案數 (想怎麼買就怎麼買,當然不買也算一種)  

 

Sample Input

5 1000
100 1500 500 500 1000

Sample Output

8

HINT

 

Source

#include<bits/stdc++.h>

#define N 45
#define M 1000007
#define ll long long

using
namespace std; ll n,m,ans,cnt,mx,flag; ll val[N],f[N][M]; inline ll read() { ll x=0,f=1;char c=getchar(); while(c>'9'||c<'0'){if(x=='-')f=-1;c=getchar();} while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();} return x*f; } void dfs(int k,ll sum) {
if(sum>m) return; if(k==n) { ans++;return; } dfs(k+1,sum); dfs(k+1,sum+val[k+1]); } void dp() { f[0][m]=1; for(int i=1;i<=n;i++) for(int j=0;j<=m;j++) { f[i][j]+=f[i-1][j]+f[i-1][j+val[i]]; } for(int i=0;i<=m;i++) ans+=f[n][i]; } int main() { //freopen("ly.in","r",stdin); n=read();m=read(); for(int i=1;i<=n;i++) val[i]=read(); if(m<=1e6) dp(); else dfs(0,0); printf("%lld\n",ans); return 0; }
80暴力 dfs+dp
/*
折半搜尋 
*/
#include<bits/stdc++.h>

#define ll long long
#define N 55

using namespace std;
ll n,m,mid,cnta,cntb,ans;
ll w[N],suma[1<<21],sumb[1<<21];

inline ll read()
 {
     ll x=0,f=1;char c=getchar();
     while(c>'9'||c<'0'){if(x=='-')f=-1;c=getchar();}
     while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
     return x*f;
 }

inline void dfs(int l,int r,ll sum,ll a[],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()
{
    n=read();m=read();
    for(int i=1;i<=n;i++)w[i]=read();;
    mid=n/2;
    dfs(1,mid,0,suma,cnta);
    dfs(mid+1,n,0,sumb,cntb);
    sort(suma+1,suma+1+cnta);
    for(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;
}