zoukankan      html  css  js  c++  java
  • [机房测试] 堆石子

    Description

    给定 (nleq 35) 堆石子,可以把一些堆合并。合并之后,石子个数为这些堆石子个数和模 (Mod),求最终能得到的最大的石子个数。

    Solution

    最多有 (2^n) 种可能的石子个数,直接搜索不行。注意到背包的可合并性质,我们折半搜索。把石子分为两边,分别处理出所有可能值,这一步 (O(2^{frac{n}{2}}))。然后考虑合并,两堆石子 (0leq a+b <2 imes Mod),对所有值排序,分类讨论,枚举 (a),找到最大的 (b),使得 (a+b<Mod),用这个更新答案,之后可以用 two-pointer 解决。对于 (a+b>Mod) 的值,最后的值是 (a+b-Mod) 是小于 (Mod) 的,所以直接贪心地取最大的 (b) 更新答案。

    #include<stdio.h>
    #include<algorithm>
    using namespace std;
    
    const int N=20;
    const int M=1<<N;
    
    int L,Mod,A[N],B[N],n,m,a[M],b[M];
    
    void dfs(int *X,int *w,int st,int ed,int s){
        if(st==ed) w[++w[0]]=s;
        else dfs(X,w,st+1,ed,s),
             dfs(X,w,st+1,ed,(s+X[st])%Mod);
    }
    
    int main(){
        freopen("stone.in","r",stdin);
        freopen("stone.out","w",stdout);
        scanf("%d%d",&L,&Mod);
        n=L/2; m=L-n; int ans=0;
        for(int i=1;i<=n;i++) scanf("%d",&A[i]);
        for(int i=1;i<=m;i++) scanf("%d",&B[i]);
        dfs(A,a,1,n+1,0),dfs(B,b,1,m+1,0);
        sort(a+1,a+1+a[0]),sort(b+1,b+1+b[0]);
        for(int i=1;i<=b[0];i++) ans=max(ans,b[i]);
        for(int i=1;i<=a[0];i++) ans=max(ans,a[i]);
        int lt=1; while(lt<=b[0]&&a[1]+b[lt]<Mod) lt++; lt--;
        for(int i=1;i<=a[0];i++){
            while(lt&&b[lt]+a[i]>=Mod) lt--;
            ans=max(ans,a[i]+b[lt]);
            ans=max(ans,(a[i]+b[b[0]])%Mod);
        }
        printf("%d",ans);
    }
    
  • 相关阅读:
    数据访问技术系列课程 笔记(2) ADO.NET 连接方式进行数据访问
    Modern C# 系列课程笔记 第11节 深入委托和事件
    idea 将项目托管到 Git 报错:Can't finish Gitee sharing process
    ADO.Net
    WebService
    2013年了
    201301杂谈
    流程图
    出错列表
    杂谈4 2012年8月15日开
  • 原文地址:https://www.cnblogs.com/wwlwQWQ/p/15501083.html
Copyright © 2011-2022 走看看