zoukankan      html  css  js  c++  java
  • [CSP-S模拟测试]:毛三琛(随机化+二分答案)

    题目传送门(内部题69)


    输入格式

    第一行正整数$n,P,k$。
    第二行$n$个自然数$a_i$。$(0leqslant a_i<P)$。


    输出格式

    仅一个数表示最重的背包的质量。


    样例

    样例输入:

    5 5 2
    0 4 2 1 3

    样例输出:

    5


    数据范围与提示

    样例解释:

    取$x=3,a={3,2,0,4,1}$。
    分配方案为${3,2,0},{4,1}$,质量最大的质量为$5$。

    数据范围:

    对于$20\%$的数据$nleqslant 20,Pleqslant 50$。
    对于$40\%$的数据$nleqslant 1,000,Pleqslant 1,000$。
    对于$100\%$的数据$nleqslant 10,000,Pleqslant 10,000$。


    题解

    枚举$x$必不可少,计算答案可以用二分答案,时间复杂度是$Theta(n imes Plog P)$的。

    如果当前枚举的$x$无论如何也无法造成更优的贡献,则不去扫。

    一个随机排列中比前面所有数都大的数的数量期望为$log$。

    然而这就是官方正解……

    时间复杂度:$Theta(n imes P+nlog nlog P)$。

    期望得分:$100$分。

    实际得分:$100$分。


    代码时刻

    #include<bits/stdc++.h>
    using namespace std;
    int n,P,K;
    int a[10001],b[10001];
    int ans=0x3f3f3f3f;
    bool judge(int x)
    {
    	int res=0,sum=0;
    	for(int i=1;i<=n;i++)
    	{
    		if(b[i]>x)return 0;
    		if(res+b[i]>x)
    		{
    			res=0;
    			sum++;
    		}
    		res+=b[i];
    	}
    	return sum<K;
    }
    int main()
    {
    	scanf("%d%d%d",&n,&P,&K);
    	for(int i=1;i<=n;i++)scanf("%d",&a[i]);
    	for(int i=0;i<P;i++)
    	{
    		int lft=0,rht=0,res=10000;
    		for(int j=1;j<=n;j++)
    		{
    			b[j]=(a[j]+i)%P;
    			rht+=b[j];
    		}
    		if(!judge(ans))continue;
    		while(lft<=rht)
    		{
    			int mid=(lft+rht)>>1;
    			if(judge(mid)){res=mid;rht=mid-1;}
    			else lft=mid+1;
    		}
    		ans=min(ans,res);
    	}
    	printf("%d",ans);
    	return 0;
    }
    

    rp++

  • 相关阅读:
    Problem: 八中上厕所
    Problem: 最短路上的统计
    股票买卖问题
    Redis(十二)——Redis为什么是单线程的?
    链表题汇总
    Redis(十一)——集群模式
    Redis(十)——哨兵模式
    Redis(九)——主从复制
    Redis(八)——客户端与服务器
    Redis(七)——事件
  • 原文地址:https://www.cnblogs.com/wzc521/p/11670339.html
Copyright © 2011-2022 走看看