zoukankan      html  css  js  c++  java
  • CF888E Maximum Subsequence

    洛咕

    题意:给定(n(n<=35))个数的数列和(m(m<=1e9)),在数列中任选若干个数,使得他们的和对(m)取模后最大,求这个最大值.

    分析:看到这个(35),很容易想到折半搜索.把数列分成相等的两个部分,分别爆搜出每个部分所有能够产生的和(在模(m)的意义下),时间复杂度为(2^{18}),很稳.

    然后对于前半部分的一个数(x),它要么是跟后半部分最大的那个与之相加不超过(m)的数(y)产生最大答案,要么是跟后半部分最大的那个数(q2[sum2])产生最大答案.

    所以我们只要考虑如何求第一种情况,显然可以把两个部分的数从小到大排序,然后两个指针来尺取就好了.

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #include<cmath>
    #include<queue>
    #include<map>
    #include<set>
    #define ll long long
    using namespace std;
    inline int read(){
        int x=0,o=1;char ch=getchar();
        while(ch!='-'&&(ch<'0'||ch>'9'))ch=getchar();
        if(ch=='-')o=-1,ch=getchar();
        while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();
        return x*o;
    }
    const int N=600005;
    int n,m,tot1,tot2,a[40],q1[N],q2[N];
    inline void dfs1(int now,ll sum){
    	q1[++tot1]=sum;if(now>n/2)return;
    	dfs1(now+1,(sum+a[now])%m);dfs1(now+1,sum);
    }
    inline void dfs2(int now,ll sum){
    	q2[++tot2]=sum;if(now>n)return;
    	dfs2(now+1,(sum+a[now])%m);dfs2(now+1,sum);
    }
    int main(){
    	n=read();m=read();for(int i=1;i<=n;++i)a[i]=read()%m;//一开始就可以取模
    	dfs1(1,0);dfs2(n/2+1,0);//折半搜索1~n/2和n/2+1~n
    	sort(q1+1,q1+tot1+1);sort(q2+1,q2+tot2+1);//两部分从小到大排序
    	int sum1=unique(q1+1,q1+tot1+1)-q1-1;
    	int sum2=unique(q2+1,q2+tot2+1)-q2-1;//去重
    	int ans=max(q1[sum1],q2[sum2]);//可能的最大答案
    	if(ans==m-1){printf("%d
    ",ans);return 0;}//如果已经是最优解了就直接输出
    	int l=0,r=sum2,L=sum2;//q1[1]=0,不用考虑了.从q1[2]开始考虑
    	while(l<=r){
    		int mid=(l+r)>>1;
    		if(q2[mid]+q1[2]>=m){
    			L=mid;r=mid-1;
    		}
    		else l=mid+1;
    	}
    	ans=max(ans,max(q1[2]+q2[L-1],(q1[2]+q2[sum2])%m));//q1[2]可能产生的最大答案
    	for(int i=3;i<=sum1;++i){
    		while(L>=2&&q2[L]+q1[i]>=m)--L;
    		ans=max(ans,max(q1[i]+q2[L],(q1[i]+q2[sum2])%m));
    	}
    	printf("%d
    ",ans);
        return 0;
    }
    
    
  • 相关阅读:
    修改浏览器滚动条样式
    js实现无缝轮播
    JS (canvas) 两个小球碰撞
    js里div随着鼠标一起移动
    js的动态加载、缓存、更新以及复用
    js阻止事件冒泡的两种方法
    核心DOM和html DOM的区别
    JavaScript 事件流、事件处理程序及事件对象总结
    css3 实现飞入由小变大
    简单手写js轮播
  • 原文地址:https://www.cnblogs.com/PPXppx/p/11679588.html
Copyright © 2011-2022 走看看