【模板】折半搜索

当n∈【30,40】可以考虑下

复杂度大概是O(2^(n/2))

算半个模板题

某位机房大佬(折半+STL)
#include<bits/stdc++.h>
using namespace std;
long long n,m,w[101],mid,a[1<<20],b[1<<20],sum1,sum2,ans;
int dfs1(int l,long long sum){
    if(sum>m) return 0;
    if(l>mid){
        a[++sum1]=sum;
        return 0;
    }
    dfs1(l+1,sum);
    dfs1(l+1,sum+w[l]);
    return 0;
}
int dfs2(int l,long long sum){
    if(sum>m) return 0;
    if(l>n){
        b[++sum2]=sum;
        return 0;
    }
    dfs2(l+1,sum);
    dfs2(l+1,sum+w[l]);
    return 0;
}
int main(){
    scanf("%lld%lld",&n,&m);
    for(int i=1;i<=n;i++) scanf("%lld",&w[i]);
    mid=n/2;
    dfs1(1,0);
    dfs2(mid+1,0);
    sort(a+1,a+1+sum1);
    for(int i=1;i<=sum2;i++){
        int t=upper_bound(a+1,a+1+sum1,m-b[i])-a-1;
        ans+=t;
    }
    printf("%lld",ans);
    return 0;
}
俺不同的做法(状压DP(半个)+二分)
#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
long long limit_1,limit_2;
long long dp1[(1<<20)],dp2[(1<<20)];
long long a[10000001];
long long mid_search(long long M){
    long long l=0,r=((long long)1<<(long long)limit_2)-(long long)1,ans=0;
    while(l<=r){
        int mid=(l+r)/2;
        if(dp2[mid]<=M){
            ans=mid;
            l=mid+1;
        }
        else r=mid-1;
    } 
    return ans+1;
}
int main(){
    long long n,m;
    scanf("%lld%lld",&n,&m);
    for(register int i=1;i<=n;i++) scanf("%lld",&a[i]);
    limit_1=(long long)n/(long long)2;
    limit_2=(long long)n-(long long)limit_1;
    for(register int i=1;i<(1<<limit_1);i++){
        for(register int j=1;j<=limit_1;j++){
            if(((1<<(j-1))&i)==0) continue;
            dp1[i]+=a[j];
        }
    }
    for(register int i=1;i<(1<<limit_2);i++){
        for(register int j=1;j<=limit_2;j++){
            if(((1<<(j-1))&i)==0) continue;
            dp2[i]+=a[j+limit_1];
        }
    }
    sort(dp1,dp1+(1<<limit_1));
    sort(dp2,dp2+(1<<limit_2));
    long long ans1=0;
    for(register int i=0;i<(1<<limit_1);i++){
        if(dp1[i]>m) break;
        ans1+=mid_search(m-dp1[i]);
    }
    printf("%lld",ans1);
    return 0;
} 

 

posted @ 2021-08-13 21:26  latent_Lin  阅读(44)  评论(0)    收藏  举报