• NOIP2002[提高组] 均分纸牌 题解


    题面

    题目保证有解即纸牌总数能被人数整除(N|T)每个人持有纸牌a[1]...a[m],我们可以先考虑第一个人

    1.若a[1]>T/M,则第一个人需要给第二个人c[1]-T/M张纸牌,即把c[2]加上c[1]-T/M。

    2.若a[1]<T/M,则第一个人需要拿第二个人c[1]-T/M张纸牌,即把c[2]减去T/M-c[1]。

    我们可以按照这种方法依次考虑2~M个人。即使某个时刻有某个c[i]被减为负数也没有关系,因为接下来c[i]就会从c[i+1]处拿纸牌。

    代码

    #include<bits/stdc++.h>
    using namespace std;
    int m,a[105],T,ans;
    int main(){
    	scanf("%d",&m);
    	for(int i=1;i<=m;++i){
    		scanf("%d",&a[i]);
    		T+=a[i];
    	}
    	T/=m;
    	for(int i=1;i<=m;++i){
    		a[i]-=T;
    	}
    	for(int i=1;i<=m;++i){
    		if(a[i]!=0){
    			a[i+1]+=a[i];
    			ans++;
    		}
    	}
    	printf("%d",ans);
    	return 0;
    }
    

    在此问题上还可进行一个拓展,若每次只能拿一张牌,思路也跟上面相同,最小步数就是

    (sum_{i=1}^M) (mid)i*T/M-G[i](mid) ,其中G是a的前缀和,即 G[i]= (sum_{j=1}^i) a[i]

    其中的含义是每个“前缀”最初有G[i]张纸牌,最后会有i*T/M张纸牌。

    如果我们设A[i]=a[i]-T/M,即一开始就让每个人手中的纸牌数都减去T/M,并且最终让每个人手里都只有0张纸牌,答案依然不变,就是

    (sum_{i=1}^M) (mid)S[i](mid)其中S是A的前缀和即 S[i]=(sum_{j=1}^i)A[i]

  • 相关阅读:
    c++:函数模板
    1084 外观数列
    1083 是否存在相等的差
    1082 射击比赛
    1081 检查密码
    1080 MOOC期终成绩
    1079 延迟的回文数
    1078 字符串压缩与解压
    1077 互评成绩计算
    1076 Wifi密码
  • 原文地址:https://www.cnblogs.com/donkey2603089141/p/11414580.html
Copyright © 2020-2023  润新知