zoukankan      html  css  js  c++  java
  • codeforces 483B Friends and Presents 解题报告

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

    题目意思:有两个 friends,需要将 cnt1 个不能整除 x 的数分给第一个friend,cnt2 个不能整除 y 的数分给第二个friend。x 和 y 都是素数来的。要求求出最小的 v,v 表示可以从1,2,...,v 中取数。

        开始我做这条题的时候是用很常规的方法做的,结果可想而知,WA,MLE,TLE。只能看题解啦,不会嘛~~~题解真是非常清晰、明白、易懂。

        等我用中文来解释下吧。要用到二分搜索!因为它符合一个条件,如果 v 这个数符合分配给两个人的所有条件,那么 v+1 就更加可以啦~~~所以二分是一个好选择,还有数据量太大啦,1e18 ! 正常做肯定超时!

        首先给出一幅本人呕心沥血画的一幅东西:

        设几个变量 f1,f2,both,others,f1',f2',v。

        v:二分枚举的数,取值是 1 ~ 1e18,图中的全集也~~~

        f1:能被 x 除尽的个数,v/f1

        f2: 能被 y 除尽的个数,v/f2  

        both:同时被 x 和 y 除尽的个数。由于 x 和 y 都是素数,所以就相当于能被 x*y 整除。v/(x*y)  

        others: 既不能被 x 也不能被 y 整除的个数。v - f1 - f2 + both (容斥原理的精髓,both 被减了两次,所以最终要加回一次)

        f1':能分配给 第二个人(除不尽 y)但又不是从others里面选择的数。f1' = f1 - both

        f2': 能分配给 第一个人(除不尽 x)但又不是从others里面选择的数。f2' = f2 - both

        然后给出的 cnt1 和 cnt2

        cnt1 = f2' + others

        cnt2 = f1' + others

        那么最终要判断的是 cnt1 - f2' + cnt2 - f1' 是否  <= others 了。因为从 others 里面取的数都符合分给两个人的条件。

        

     1 #include <iostream>
     2 #include <cstdio>
     3 #include <cstdlib>
     4 #include <cstring>
     5 #include <algorithm>
     6 using namespace std;
     7 
     8 typedef __int64 LL;
     9 LL cnt1, cnt2, x, y;
    10 
    11 bool check(LL v)
    12 {
    13     LL f1 = v / x;
    14     LL f2 = v / y;
    15     LL both = v / (x*y);
    16     LL others = v - f1 - f2 + both;
    17     LL ff1 = f1 - both;  // second
    18     LL ff2 = f2 - both;  // first
    19 
    20     LL gf1 = (cnt1 - ff2 >= 0 ? cnt1 - ff2 : 0);   // 注意这个相减有可能为负数,所以要判断下
    21     LL gf2 = (cnt2 - ff1 >= 0 ? cnt2 - ff1 : 0);
    22 
    23     return (gf1 + gf2 <= others);
    24 }
    25 
    26 int main()
    27 {
    28     while (scanf("%I64d%I64d%I64d%I64d", &cnt1, &cnt2, &x, &y) != EOF)
    29     {
    30         LL l = 1, r = 1e18;
    31         while (l < r)
    32         {
    33             LL m = (l+r) >> 1;
    34             if (check(m))
    35                 r = m;
    36             else
    37                 l = m + 1;
    38         }
    39         printf("%I64d
    ", r);
    40     }
    41     return 0;
    42 }
  • 相关阅读:
    蓝桥杯 十六进制转八进制
    蓝桥杯 字母图形
    2017.12.13T19_B2_5mianshiti
    2017.11.21T19_B2_6.2讲义
    2017.12.13T19_B2_6zuoye
    2017.12.1T19_B2_5zuoye
    2017.12.1T19_B2_4zuoye
    2017.12.1T19_B2_4——2
    2017.12.1T19_B2_4.3kehouzuoye
    2017.12.1T19_B2_4.2
  • 原文地址:https://www.cnblogs.com/windysai/p/4058235.html
Copyright © 2011-2022 走看看