[1651] Red packet【二分】

来源:互联网 发布:java基础知识txt下载 编辑:程序博客网 时间:2024/04/30 10:33

  • [1651] Red packet

  • 时间限制: 1000 ms 内存限制: 65535 K
  • 问题描述
  • New Year is coming! Our big boss Wine93 will distribute some “Red Package”, just like Alipay and Wechat.

    Wine93 has m yuan, he decides to distribute them to n people and everyone can get some money(0 yuan is not allowed and everyone’s money is an integer), Now k people has gotten money, it’s your turn to get “Red Package”, you want to know, at least how much money to give you, then you can become the “lucky man”. and the m yuan must be used out.

    Noting that if someone’s money is strictly much than others’, than he is “lucky man”.


  • 输入
  • Input starts with an integer T (T <= 50) denoting the number of test case.
    For each test case, three integers n, m, k (1 <= k < n <= 100000, 0< m <= 100000000) will be given.
    Next line contains k integers, denoting the money that k people get. You can assume that the k integers’ summation is no more than m.
  • 输出
  • Ouput the least money that you need to become the “lucky man”, if it is impossible, output “Impossible” (no quote).
  • 样例输入
  • 33 5 22 14 10 22 34 15 23 5
  • 样例输出
  • Impossible46

这道题做的真让我伤心。昨晚做了两个小时一直在wa就是不知道那错了。然后上午一直在看这道题在oj上交了40多遍一直wa快崩溃了都。最后问题出题人题解才明白原来是我把题意弄错了。。。。

再说一下题意吧问的是人能获得最少多少钱可以让他成为运气王即运气王的钱数严格大于其他人的钱数。这里的最少的钱的含义是。把剩下的钱给其他人分无论。怎么分运气王仍是此人。而我却理解为一种特定的分钱情况满足此人为运气王且钱数最少。给一组数据说明一下。

1

6 31 1

5

正确答案是12而按照我的想法可以这样分5 6 5 5 5 5 这样答案是6这样不能保证其始终为运气王。

AC代码:

#include<cstdio>#include<cstdlib>#include<cstring>#include<algorithm>#include<cmath>#include<queue>#include<list>#include<queue>#include<vector>using namespace std;int main(){int t,n,m,i,j,k;scanf("%d",&t);while(t--){scanf("%d%d%d",&n,&m,&k);int sum=0,num,maxm=0;for(i=0;i<k;++i){scanf("%d",&num);sum+=num;maxm=max(maxm,num);}int l=n-k,cnt=m-sum;;if(cnt<=maxm){printf("Impossible\n");}else if(l==1){printf("%d\n",cnt);}else {int l=maxm+1,r=cnt-(n-k-1),ans=-1;if(r<l){printf("Impossible\n");}else {while(l<=r){int mid=(l+r)>>1;if(2*mid+n-k-2<=cnt){l=mid+1;}else {ans=mid;r=mid-1;}}if(ans==-1){printf("Impossible\n");}else {printf("%d\n",ans);}}}}return 0;}


按照我的想法写的代码:

#include<cstdio>#include<cstdlib>#include<cstring>#include<algorithm>#include<cmath>#include<list>#include<queue>#include<vector>using namespace std;const int maxn=100010;int num;int main(){int i,j,k,n,m,t;scanf("%d",&t);while(t--){scanf("%d%d%d",&n,&m,&k);int maxm=0,sum=0;for(i=0;i<k;++i){scanf("%d",&num);sum+=num;maxm=max(maxm,num);}int ans=m-sum;if(ans<=maxm){printf("Impossible\n");}else {int l=n-k;if(l==1){printf("%d\n",ans);continue;}else if((ans-maxm-1)/(l-1)<maxm){if((ans-maxm-1)/(l-1)<=0){printf("Impossible\n");continue;}else printf("%d\n",maxm+1);}else {int money=ans/l;if(ans%l==0){if(money<=1){printf("Impossible\n");}else printf("%d\n",money+1);}else if(ans%l==1){printf("%d\n",money+1);}else if(ans%l>=2){printf("%d\n",money+2);}}}}return 0;}


0 0