4800: [Ceoi2015]Ice Hockey World Championship(折半搜索)
4800: [Ceoi2015]Ice Hockey World Championship
Time Limit: 10 Sec Memory Limit: 256 MBSubmit: 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
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;
}
/*
折半搜索
*/
#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;
}
折花枝,恨花枝,准拟花开人共卮,开时人去时。
怕相思,已相思,轮到相思没处辞,眉间露一丝。