zoukankan      html  css  js  c++  java
  • 【2018暑假集训模拟一】Day1题解

    T1准确率

    【题目描述】

    你是一个骁勇善战、日刷百题的OIer. 今天你已经在你OJ 上提交了y 次,其中x次是正确的,这时,你的准确率是x/y.
    然而,你最喜欢一个在[0; 1] 中的有理数p/q(是一个既约分数),所以你希望再进行若干次提交,使你的准确率变为p/q. 当然,由于你的实力很强,你可以随意决定进行多少次正确的提交和多少次错误的提交. 同时,你不希望把一天的时间都用在提交上,所以你想求出最少还要进行多少次提交(包括正确的和错误的),才能达到这一目标.
    注意:本题中,0/1 和1/1 都是既约分数.


    【输入格式】
    从文件rate.in 中读入数据。
    输入第一行包含一个正整数t (t <= 5 * 10 ^ 5),表示数据组数.
    接下来t 行,每行4 个整数x, y, p, q (0 <= x <= y <= 10 ^ 9; 0 <= p <= q <= 10 ^ 9; y > 0; q > 0),含义如题所述.


    【输出格式】
    输出到文件rate.out 中。
    输出t 行,每行一个整数,表示使正确率达到p/q 所需最小提交次数;若无法达到,输出-1.


    【样例1 输入】
    4
    3 10 1 2
    7 14 3 8
    20 70 2 7
    5 6 1 1


    【样例1 输出】
    4
    10
    0
    -1

    【样例1 解释】
    第一组数据中,你需要进行4 次正确的提交,使准确率达到7/14,即1/2;
    第二组数据中,你需要进行2 次正确的提交,8 次错误的提交,使准确率变为9/24,即3/8;
    第三组数据中,你无需进行任何提交,因为你的准确率已为20/70,即2/7;
    第四组数据中,在原有的提交中已有一次错误提交,准确率不可能达到1.


    【样例2】
    见选手目录下的rate/rate2.in 与rate/rate2.ans。

    【子任务】
    对于30% 的数据,t = 1;
    对于另30% 的数据,t <= 1000.
    以上两部分数据中,各有50% 的数据保证x, y, p, q <= 10 ^ 4.

     

    题意很明了,然后别想偏了……

    首先不要把x, y约分要不然答案肯定不对,这是挺显然的。

    然后不要把这题想成数论的不定方程,虽然设完正确提交和错误提交后化简一下确实很像不定方程,然而会有负数,而且这块我有些地方还是不太懂,所以肯定不是这个做法……

    实际上,这不过是一道初中不等式,只要将p, q同时扩大n倍后,满足n * p >= x && n * q >= y就行了。

     1 #include<cstdio>
     2 #include<iostream>
     3 #include<cmath>
     4 #include<algorithm>
     5 #include<cstring>
     6 #include<cstdlib>
     7 #include<cctype>
     8 #include<vector>
     9 #include<stack>
    10 #include<queue>
    11 using namespace std;
    12 #define enter printf("
    ")
    13 #define space printf(" ")
    14 #define Mem(a) memset(a, 0, sizeof(a))
    15 typedef long long ll;
    16 typedef double db;
    17 const int INF = 0x3f3f3f3f;
    18 const int eps = 1e-8;
    19 //const int maxn = ;
    20 inline ll read()
    21 {
    22     ll ans = 0;
    23     char ch = getchar(), last = ' ';
    24     while(!isdigit(ch)) {last = ch; ch = getchar();}
    25     while(isdigit(ch))
    26     {
    27         ans = ans * 10 + ch - '0'; ch = getchar();
    28     }
    29     if(last == '-') ans = -ans;
    30     return ans;
    31 }
    32 inline void write(ll x)
    33 {
    34     if(x < 0) x = -x, putchar('-');
    35     if(x >= 10) write(x / 10);
    36     putchar(x % 10 + '0');
    37 }
    38 
    39 int t;
    40 
    41 int main()                //代码就这么短…… 
    42 {
    43     freopen("rate.in", "r", stdin);
    44     freopen("rate.out", "w", stdout);
    45     t = read();
    46     while(t--)
    47     {
    48         ll a = read(), b = read(), p = read(), q = read();
    49         if(p == q) printf("%s
    ", x == y ? "0" : "-1");
    50         else if(p == 0) printf("%s
    ", x == 0 ? "0" : "-1");
    51         else
    52         {
    53             ll n = max((x - 1) / p, (y - x - 1) / (q - p)) + 1;
    54             write(n * q - y); enter;
    55         }
    56     }
    57     return 0;
    58 }

    T2 模拟赛

    【题目描述】
    你很快地完成了所有的题目,并且使准确率达到了p/q,于是开始无所事事. 老师看见了,对你说:“你今天做的题够多的了,别再做了. 我们接下来k 天每天都要模拟,我这里有很多题,你去选一些题目编k 场模拟赛吧. ”老师将所有题目都编了序号,还给你了n 种出题方案(所有方案两两不同). 每种出题方案选择所有编号属于[l; r] 的题目,作为一天的试题. 现在,你需要选出k 种出题方案(一个方案只能选取一次),分别对应k 天的模拟赛. 老师非常强调复习的重要性,因此希望有一些题目每天都出现在模拟赛当中,你需要最大化每天都出现的题目的数量.


    【输入格式】
    从文件exam.in 中读入数据。
    输入第一行包含两个正整数n; k (1 <= k <= n <= 3 * 10 ^ 5),分别为出题方案数和模拟赛天数.
    接下来n 行,每行两个整数l; r (-10 ^ 9 <= l <= r <= 10 ^ 9),表示一个出题方案(保证所有方案两两不同).


    【输出格式】
    输出到文件exam.out 中。
    输出一个非负整数,表示每天都出现的题目的数量的最大值.


    【样例1 输入】
    4 2
    1 100
    40 70
    120 130
    125 180


    【样例1 输出】
    31


    【样例1 解释】
    选择前两种方案,编号为[40; 70] 的题目在两种方案中均出现,共有31 道题.

    【样例2 输入】
    3 2
    1 12
    15 20
    25 30


    【样例2 输出】
    0


    【样例2 解释】
    所有给出的方案互不相交,所以答案为0.

    【子任务】
    对10% 的数据,k = n;
    对另20% 的数据,k = 2;
    对另20% 的数据,1 <= k <= n <= 20;
    其余5 组数据,n = 10 ^ 2, 10 ^ 3, 10 ^ 4, 10 ^ 5, 3 * 10 ^ 5.

    简单来说,就是让你从给定的n个区间中找出k个区间,使这k个区间的公共部分长度最大。

    很容易想到,在所选的区间中,公共部分的长度是由最大的左端点的和最小的右端点控制的。那么如果我们先把所有区间按左端点排序,然后枚举左端点,那么控制公共区间长度的就是当前的左端点和最小的右端点。因此我们只要想办法维护所选区间的右端点就行了。
    O(n ^ 2)的做法是,对于每一个区间,从左端点比他小的区间中选出右端点最大的 k-1 个区间,其中右端点第k-1大的就是当前公共区间的右端点。

    然后我们就可以用一个堆优化选取这个右端点的过程,把所选的区间的右端点都放到小根堆里,当堆中元素大于k个或是根的右端点比当前左端点小,就删除根,然后当枚举到第i个区间时的答案就是 q.top() - a[i].L +1,并尝试用这个更新答案。

     1 #include<cstdio>
     2 #include<iostream>
     3 #include<cmath>
     4 #include<algorithm>
     5 #include<cstring>
     6 #include<cstdlib>
     7 #include<cctype>
     8 #include<vector>
     9 #include<stack>
    10 #include<queue>
    11 #include<set>
    12 using namespace std;
    13 #define enter printf("
    ")
    14 #define space printf(" ")
    15 #define Mem(a) memset(a, 0, sizeof(a))
    16 typedef long long ll;
    17 typedef double db;
    18 const int INF = 0x3f3f3f3f;
    19 const int eps = 1e-8;
    20 const int maxn = 3e5 + 5;
    21 inline ll read()
    22 {
    23     ll ans = 0;
    24     char ch = getchar(), last = ' ';
    25     while(!isdigit(ch)) {last = ch; ch = getchar();}
    26     while(isdigit(ch))
    27     {
    28         ans = ans * 10 + ch - '0'; ch = getchar();
    29     }
    30     if(last == '-') ans = -ans;
    31     return ans;
    32 }
    33 inline void write(ll x)
    34 {
    35     if(x < 0) x = -x, putchar('-');
    36     if(x >= 10) write(x / 10);
    37     putchar(x % 10 + '0');
    38 }
    39 
    40 int n, k;
    41 struct Node
    42 {
    43     int L, R;
    44     bool operator < (const Node& other)const
    45     {
    46         return L < other.L || (L == other.L && R < other.R);
    47     }
    48 }a[maxn];
    49 
    50 
    51 struct QUE            //忘了优先队列的小根堆写法…… 
    52 {
    53     int l;
    54     bool operator < (const QUE& other)const
    55     {
    56         return l > other.l;
    57     }
    58 };
    59 priority_queue<QUE> q;
    60 int cnt = 0, ans = 0;
    61 
    62 int main()
    63 {
    64     freopen("exam.in", "r", stdin);
    65     freopen("exam.out", "w", stdout);
    66     n = read(); k = read();
    67     for(int i = 1; i <= n; ++i) {a[i].L = read(); a[i].R = read();}
    68     sort(a + 1, a + n + 1);
    69     for(int i = 1; i <= n; ++i)
    70     {
    71         q.push((QUE){a[i].R}); cnt++;
    72         if(cnt > k) {q.pop(); cnt--;}
    73         while(!q.empty() && a[i].L > q.top().l) {q.pop(); cnt--;}
    74         if(cnt == k) ans = max(ans, q.top().l - a[i].L + 1);
    75     }
    76     write(ans); enter;
    77     return 0;
    78 }

    T3还不会呀……(小声)

  • 相关阅读:
    wcf技术博客
    MFC程序崩溃的友好处理
    DESCryptoServiceProvider 类
    AttributeUsage AttributeTargets
    Word 2007第n级编号不自动按照父级标题自动编号 的解决办法
    suo的作用
    "在唯一密钥属性“name”设置为“Application”时,无法添加类型为“add”的重复集合项"
    PMP考试中的成本管理英文缩写及其含义
    删除右键新建菜单中的多余项
    使用命令行启动服务
  • 原文地址:https://www.cnblogs.com/mrclr/p/9442658.html
Copyright © 2011-2022 走看看