zoukankan      html  css  js  c++  java
  • codeforces B. Valera and Contest 解题报告

    题目链接:http://codeforces.com/problemset/problem/369/B

    题目意思:给出6个整数, n, k, l, r, sall, sk ,需要找出一个满足下列条件的序列:1、 l <= 每一个数 <= r   2、整个序列的数的和为sall       3、取得最高分数的那k个人的总分数恰好(注意,是刚刚好,多了或少了都不可,而且这k个人的分数不一定都是相等的)等于sk。(至于后面的那句 if a1, a2, ..... sk = a1 + a2 + ... + ak 本人觉得好像没有什么多大的用处)

         wa足9次终于做出来了。一开始以为取得最高分,那么非r莫属,直接输出k 个 r 即可,接着下面的 (sallsk  )/ (n-k) 根据有无余数来继续。真的是大错特错啊~~陆陆续续修改,又没有考虑到 sall  sk  

          模拟题真的不是很难,但是要十分细心!

          我的做法是,求k个人和n-k个人的分数的做法类似,所以可以写一个函数solve来解决。 以求k个人的分数为例,前面已经交代k个人的分数不一定完全相同,也就是说有余数(sk / k 不是恰好是整数,那么就要回溯,那么令 i = 1,即 sk / k  *  (k-i) (用p3表示),剩下的数为sk-p3 。试探它是否刚好能够除得尽 i,除此,还需要满足在[l,r]的范围,当找到第一个满足条件的i即可跳出循环。 至于求n-k个,稍稍有点不同的是,求出的商还需要满足比第一次调用求出的所有数要少(题目意思啊!),其实就是要小于两个数即可,即代码中的res1 和 res2

     1 #include <iostream>
     2 #include <cstdlib>
     3 #include <cstdio>
     4 using namespace std;
     5 
     6 int n, k, l, r, sum, sumk, cnt, res1, res2;   //cnt的使用是为了区别第一次的调用和第二次的调用
     7 
     8 void solve(int p, int n)
     9 {
    10     int i, j, p1, p2, p3, p4, p5, flag = 0;
    11     cnt++;
    12     p1 = p/n;
    13     if (p % n)
    14     {
    15         for (i = 1; !flag; i++)
    16         {
    17             p3 = p1 * (n - i);
    18             p2 = p - p3;
    19             if (p2 % i == 0)
    20             {
    21                 p4 = p2 / i;
    22                 if (p4 <= r && p4 >= l)
    23                 {
    24                     if (cnt == 1)    // 第一次调用,求k个数
    25                     {
    26                         p5 = p4;
    27                         flag = 1;
    28                         res1 = p5;
    29                         res2 = p1;      
    30                         break;
    31                     }
    32                     else if (cnt == 2)  // 第二次调用,求n-k个数
    33                     {
    34                         if (p4 <= res1 && p4 <= res2)  // 这个条件好关键,保证是比第一次调用所求出的所有数要少
    35                         {
    36                             p5 = p4;
    37                             flag = 1;
    38                             break;
    39                         }
    40                     }
    41                 }
    42             }
    43         }
    44         for (j = 0; j < n-i; j++)
    45             printf("%d ", p1);
    46         for (j = 0; j < i; j++)
    47         {
    48             if (flag)
    49                 printf("%d ", p5);
    50             else
    51                 printf("%d ", p1);
    52         }
    53     }
    54     else
    55     {
    56         if (cnt == 1)
    57             res1 = res2 = p1;   // 好关键的,有可能第一次调用k个人的分数完全相等
    58         for (i = 1; i <= n; i++)
    59             printf("%d ", p1);
    60     }
    61 }
    62 int main()
    63 {
    64     int t1, t2;
    65     while (scanf("%d%d%d%d%d%d", &n, &k, &l, &r, &sum, &sumk) != EOF)
    66     {
    67         cnt = 0;
    68         solve(sumk, k); 
    69         if (sum != sumk)   // 如果相等,没有必要调用第二次
    70         {
    71             t1 = sum - sumk;
    72             t2 = n-k;  
    73             solve(t1, t2);
    74         }   
    75         printf("
    ");
    76     }
    77     return 0;
    78 }

        简化后的代码(参考乌冬兄的代码,这就是差距啊~~~)

      

     1 #include <iostream>
     2 #include <cstdio>
     3 #include <cstdlib>
     4 #include <vector>
     5 using namespace std;
     6 
     7 int main()
     8 {
     9     int n, k, l, r, sall, sk, i;
    10     while (scanf("%d%d%d%d%d%d", &n, &k, &l, &r, &sall, &sk) != EOF)
    11     {
    12         vector<int> res(n,l);  //n个元素,每个元素初始值为l
    13         sk -= k * l;    //k个人分数之和的最大余数
    14         sall -= n * l + sk;  //n-k个人分数之和的最大余数
    15         for (i = 0; i < k; i++)
    16             res[i] += sk/k;    //有可能有余数的,所以后面要接着判断
    17         for (i = 0; i < sk%k; i++) //每一个都加,保证每个数都增长得最慢(有r限制)
    18             res[i]++;
    19         if (sall) //如果为0,说明剩下的n-k个人的分数都为l
    20         {
    21             for (i = k; i < n; i++)  //注意是从k开始加,保证题目中所说的前k个人的分数是整个序列中最大的
    22                 res[i] += sall / (n-k);
    23             for (i = k; i < k+sall%(n-k); i++)
    24                 res[i]++;
    25         }
    26         for (i = 0; i < res.size(); i++)
    27             printf("%d ", res[i]);
    28         printf("
    ");
    29     }
    30     return 0;
    31 }
  • 相关阅读:
    Server Apache Tomcat v7.0 at localhost failed to start.
    iOS-UITextField、一些知识点
    iOS-UIButton
    iOS-URL
    iOS-UITableView(三)
    iOS-MVC(转)
    iOS-UITableView(二)
    iOS-UITableView(一)
    iOS-UIScrollView以及代理
    iOS-UIView常见方法、xib的基本使用
  • 原文地址:https://www.cnblogs.com/windysai/p/3451791.html
Copyright © 2011-2022 走看看