NOIP模拟17.9.22

前进!
【问题描述】
数轴的原点上有一只青蛙。青蛙要跳到数轴上≥ 的位置去,但很不幸数轴
上有个区间是禁区,不能进入。青蛙会选择一个长度,从原点开始每次向右
跳长度为的一段。一路上青蛙会停的位置是0, , 2,…直到跳到了≥ 的位置,
任意一个位置都不能在禁区中。请求出的最小值,注意可以是实数。
【输入格式】
输入文件为susume.in。
输入文件的第一行包含两个整数和,含义如问题描述中所述。
接下来行,每行描述一个禁区。每行有两个整数和,代表数轴上(, )的
区间是禁区。保证有0 ≤ < ≤ 。
【输出格式】
输出文件为susume.out。
输出一行,代表的最小值。精度要求请参考评分方法。
【样例输入1】
2 25
11 21
3 7
【样例输出1】
10.5
【样例1 解释】
第一步跳到了 = 10.5,第二步跳到 = 21,第三步就跳到了≥ 的位置。
可以证明这个解是最小的解。
【样例输入2】
2 100
0 50
50 100
【样例输出2】
50.0

【题解】

考场上想出正解,但是因为SPJ所以没测

不难证明一定会在某次跳跃跳到某个区间的右端点

这样我们枚举是哪一个右端点,不断/2,/3,/4.../r作为

步长L。然后在On时间判断是否合法即可

挂标称了

  1. 1 //#line 7 "TheFrog.cpp"
  2. 2 #include <cstdlib>
  3. 3 #include <cstring>
  4. 4 #include <cstdio>
  5. 5 #include <cmath>
  6. 6 #include <climits>
  7. 7 #include <algorithm>
  8. 8 #include <vector>
  9. 9 #include <string>
  10. 10 #include <iostream>
  11. 11 #include <map>
  12. 12 #include <queue>
  13. 13 #include <utility>
  14. 14 #include <ctime>
  15. 15 #include <sstream>
  16. 16 using namespace std;
  17. 17
  18. 18 typedef long long ll;
  19. 19 #define pair(x, y) make_pair(x, y)
  20. 20
  21. 21 #define N 50
  22. 22
  23. 23 class TheFrog {
  24. 24 public:
  25. 25 static const double eps = 1e-9;
  26. 26
  27. 27 pair<double, double> p[N + 1];
  28. 28 int n, D_;
  29. 29 double ans, m;
  30. 30
  31. 31 inline bool check(double x) {
  32. 32 for (int i = 1; i <= n; ++i) {
  33. 33 int ds = (int)(p[i].first / x + eps);
  34. 34 if (x * (double)(ds + 1) < p[i].second - eps)
  35. 35 return false;
  36. 36 }
  37. 37 return true;
  38. 38 }
  39. 39
  40. 40 double getMinimum(int D, vector <int> L, vector <int> R) {
  41. 41 ans = 1e10, m = 1e10, D_ = D;
  42. 42 n = L.size();
  43. 43 for (int i = 1; i <= n; ++i) p[i] = pair((double)L[i - 1], (double)R[i - 1]);
  44. 44 for (int i = 0; i < n; ++i) m = min(m, (double)R[i] - L[i]);
  45. 45 sort(p + 1, p + n + 1);
  46. 46 for (int i = 1; i <= n; ++i) {
  47. 47 double x = p[i].second;
  48. 48 int div = (int)(x / ans);
  49. 49 while (x / (double)div > m - eps) {
  50. 50 if (check(x / (double)div)) ans = min(ans, x / (double)div);
  51. 51 ++div;
  52. 52 }
  53. 53 }
  54. 54 return ans;
  55. 55 }
  56. 56 };
  57. 57
  58. 58 int n, D;
  59. 59 vector <int> L, R;
  60. 60
  61. 61 int main() {
  62. 62 freopen("susume.in", "r", stdin);
  63. 63 freopen("susume.out", "w", stdout);
  64. 64
  65. 65 TheFrog solution;
  66. 66 scanf("%d%d", &n, &D);
  67. 67 for (int i = 1; i <= n; ++i) {
  68. 68 int l, r;
  69. 69 scanf("%d%d", &l, &r);
  70. 70 L.push_back(l), R.push_back(r);
  71. 71 }
  72. 72
  73. 73 double ans = solution.getMinimum(D, L, R);
  74. 74 printf("%.10lf\n", ans);
  75. 75
  76. 76 fclose(stdin);
  77. 77 fclose(stdout);
  78. 78 return 0;
  79. 79 }

T1

统计
【问题描述】
给定长度为的序列。记 = {<, =,…, >},你需要计算下面的表达式的值:
max
C∈E
− min
I∈E

E⊆L
E MN
说得通俗一点,就是序列的元素构成了集合(序列中值相同的多个元素
在中也被视为不同的元素),求的所有大小为的子集中,元素的最大值减最
小值,之和。
由于答案可能很大,输出答案对取模之后得到的结果。
【输入格式】
输入数据的第一行包含三个整数、和。
接下来一行,包含个整数,代表序列。
【输出格式】
输出一行,包含一个整数,即为答案。
【样例】
setdiff.in setdiff.out
4 2 10007
10 20 30 40
100
【样例解释】
一共有6 个可选的子集:
• {10, 20},最大值为20,最小值为10;
• {10, 30},最大值为30,最小值为10;
• {10, 40},最大值为40,最小值为10;
• {20, 30},最大值为30,最小值为20;
• 20, 40 ,最大值为40,最小值为20;
• {30, 40},最大值为40,最小值为30。
【数据规模和约定】
对于30%的数据, ≤ 20。
对于60%的数据, ≤ 5000。
对于100%的数据,1 ≤ ≤ ≤ 100000,0 ≤ R ≤ 106,2 ≤ ≤ 106 + 7且
为质数。

【题解】

这个题的那个绝对值太迷惑了,去掉绝对值肯定知道

把式子化一下啊,真是蠢啊。。。。。。。。。

排个序,组合算一下就好了

  1. 1 #include <iostream>
  2. 2 #include <cstdio>
  3. 3 #include <cstdlib>
  4. 4 #include <cstring>
  5. 5 #include <algorithm>
  6. 6 #define max(a, b) ((a) > (b) ? (a) : (b))
  7. 7 #define min(a, b) ((a) < (b) ? (a) : (b))
  8. 8
  9. 9 inline void read(long long &x)
  10. 10 {
  11. 11 x = 0;char ch = getchar(), c = ch;
  12. 12 while(ch < '0' || ch > '9')c = ch, ch = getchar();
  13. 13 while(ch <= '9' && ch >= '0')x = x * 10 + ch - '0', ch = getchar();
  14. 14 if(c == '-')x = -x;
  15. 15 }
  16. 16
  17. 17 const int INF = 0x3f3f3f3f;
  18. 18 const int MAXN = 100000 + 10;
  19. 19
  20. 20 long long n, k, p, num[MAXN], ans, f[MAXN];
  21. 21
  22. 22 long long pow(long long a, long long b)
  23. 23 {
  24. 24 long long r = 1, base = a % p;
  25. 25 for(;b;b >>= 1)
  26. 26 {
  27. 27 if(b & 1) r *= base, r %= p;
  28. 28 base *= base, base %= p;
  29. 29 }
  30. 30 return r;
  31. 31 }
  32. 32
  33. 33 inline long long ni(long long num)
  34. 34 {
  35. 35 return pow(num, p - 2);
  36. 36 }
  37. 37
  38. 38 long long C(long long n, long long m)
  39. 39 {
  40. 40 if(n < m)return 0;
  41. 41 return ((f[n] * ni(f[m]))%p * ni(f[n - m]))%p;
  42. 42 }
  43. 43
  44. 44 int main()
  45. 45 {
  46. 46 read(n), read(k), read(p);
  47. 47 f[0] = 1;
  48. 48 for(register int i = 1;i <= n;++ i)
  49. 49 f[i] = f[i - 1] * i, f[i] %= p;
  50. 50 for(register int i = 1;i <= n;++ i)
  51. 51 read(num[i]);
  52. 52 std::sort(num + 1, num + 1 + n);
  53. 53 for(register int i = k;i <= n;++ i)
  54. 54 ans += C(i - 1, k - 1) * (num[i] % p) % p;
  55. 55 std::sort(num + 1, num + 1 + n, std::greater<int>());
  56. 56 for(register int i = k;i <= n;++ i)
  57. 57 ans -= C(i - 1, k - 1) * (num[i] % p) % p, ans = (ans%p + p)%p;
  58. 58 printf("%d", ans);
  59. 59 return 0;
  60. 60 }

T2

旅行
【问题描述】
给定一个长度为的序列<, =,…, >。定义序列的代价为R − RU<
>5<
RM< 。
你现在可以任意次交换相邻的两个数,但是除了第一次交换以外,每次交换
的两个数的位置都应该在前一次交换的两个数的位置的右边。
比如说,第一次交换了(=, 7)这两个数,第二次就不能交换(<, =)或者
(=, 7),但是可以交换(7, V)或者(V, W)等。
求任意交换之后序列的最小代价。
【输入格式】
输入数据第一行一个整数。
接下来一行包含个整数,代表数列的每个元素。
【输出格式】
输出一行,代表最小代价。
【样例输入】
4
2 3 4 1
【样例输出】
4
【样例解释】
第一次,交换(<, =),数列变成{3,2,4,1}。
第二次,交换(=, 7),数列变成{3,4,2,1}。
可以证明这是最优方案。
【数据规模和约定】
对于10%的数据, ≤ 10。
对于20%的数据, ≤ 18。
对于50%的数据, ≤ 100。
对于100%的数据, ≤ 2000,R ≤ 100000。

【题解】

DP神题。

我们把i标位1意味着i与i + 1交换

i标位0意味着i与i + 1不交换

我们发现如果两个1之间夹着0,那么这两个1互不影响

如果是连续的一串1,起点l,终点r,由于必须从左向右

进行,其实相当于做了一次循环移动,变成了l,l+1,l+2.。。。r-1,r,l

于是我们在序列上做DP

因为是i与i + 1交换,i可以从i +  1转移过来,

为了方便计算, 我们用倒推。

dp[i][0]表示i这个位置放1,即第i个数与第i + 1个数交换,从i...n的最小代价

dp[i][1]表示i这个位置放0,即第i个数与第i + 1个数不交换,从i...n的最小代价

转移的时,0比较显然,1我们就枚举连续1的长度即可

有很多细节,转移详见代码

  1. 1 #include <iostream>
  2. 2 #include <cstdio>
  3. 3 #include <cstdlib>
  4. 4 #include <cstring>
  5. 5 #define max(a, b) ((a) > (b) ? (a) : (b))
  6. 6 #define min(a, b) ((a) < (b) ? (a) : (b))
  7. 7 #define abs(a) ((a) < 0 ? (-1 * (a)) : (a))
  8. 8
  9. 9 inline void read(int &x)
  10. 10 {
  11. 11 x = 0;char ch = getchar(), c = ch;
  12. 12 while(ch < '0' || ch > '9')c = ch, ch = getchar();
  13. 13 while(ch <= '9' && ch >= '0')x = x * 10 + ch - '0', ch = getchar();
  14. 14 if(c == '-')x = -x;
  15. 15 }
  16. 16
  17. 17 const int INF = 0x7fffffff;
  18. 18 const int MAXN = 10000 + 10;
  19. 19
  20. 20 int dp[MAXN][2], sum[MAXN], num[MAXN], n;
  21. 21
  22. 22 int main()
  23. 23 {
  24. 24 read(n);
  25. 25 for(register int i = 1;i <= n;++ i)
  26. 26 read(num[i]);
  27. 27 for(register int i = 2;i <= n;++ i)
  28. 28 sum[i] = sum[i - 1] + abs(num[i] - num[i - 1]);
  29. 29 for(register int i = n - 1;i >= 1;-- i)
  30. 30 {
  31. 31 if(i == n - 1)
  32. 32 dp[i][0] = abs(num[i + 1] - num[i]);
  33. 33 else
  34. 34 dp[i][0] = min(dp[i + 1][0] + abs(num[i] - num[i + 1]),
  35. 35 dp[i + 1][1] + abs(num[i] - num[i + 2]));
  36. 36 dp[i][1] = INF;
  37. 37 for(register int j = i + 1;j < n - 1;++ j)
  38. 38 {
  39. 39 dp[i][1] = min(dp[i][1],
  40. 40 abs(num[i] - num[j]) + sum[j] - sum[i + 1] +
  41. 41 min(dp[j + 1][0] + abs(num[i] - num[j + 1]),
  42. 42 dp[j + 1][1] + abs(num[i] - num[j + 2])));
  43. 43 }
  44. 44 if(i <= n - 2)
  45. 45 dp[i][1] = min(dp[i][1],
  46. 46 sum[n - 1] - sum[i + 1] + abs(num[i] - num[n - 1]) + abs(num[i] - num[n]));
  47. 47 dp[i][1] = min(dp[i][1],
  48. 48 sum[n] - sum[i + 1] + abs(num[n] - num[i]));
  49. 49 }
  50. 50 printf("%d", min(dp[1][0], dp[1][1]));
  51. 51 return 0;
  52. 52 }

T3

NOIP模拟17.9.22的更多相关文章

  1. NOIP模拟17.9.21

    NOIP模拟17.9.21 3 58 145 201 161.5 样例输出21.6 数据规模及约定对于40% 的数据,N <= 20对于60% 的数据,N <= 1000对于100% 的数 ...

  2. NOIP模拟 17.8.20

    NOIP模拟17.8.20 A.阶乘[题目描述]亲爱的xyx同学正在研究数学与阶乘的关系,但是他喜欢颓废,于是他就制作了一个和阶乘有关系的数学游戏:给出两个整数 n,m,令 t = !n,每轮游戏的流 ...

  3. NOIP模拟 17.8.18

    NOIP模拟17.8.18 A.小菜一碟的背包[题目描述]Blice和阿强巴是好朋友但萌萌哒Blice不擅长数学,所以阿强巴给了她一些奶牛做练习阿强巴有 n头奶牛,每头奶牛每天可以产一定量的奶,同时也 ...

  4. NOIP模拟 17.8.15

    NOIP模拟17.8.15 A 债务文件名 输入文件 输出文件 时间限制 空间限制debt.pas/c/cpp debt.in debt.out 1s 128MB[题目描述]小 G 有一群好朋友,他们 ...

  5. NOIP模拟 17.8.17

    NOIP模拟17.8.17 A 小 G 的字符串文件名 输入文件 输出文件 时间限制 空间限制str.pas/c/cpp str.in str.out 1s 128MB[题目描述]有一天,小 L 给小 ...

  6. NOIP模拟 17.8.16

    NOIP模拟17.8.16 A 债务文件名 输入文件 输出文件 时间限制 空间限制debt.pas/c/cpp debt.in debt.out 1s 128MB[题目描述]小 G 有一群好朋友,他们 ...

  7. NOIP模拟 17.8.14

    NOIP模拟17.8.14 (天宇哥哥考察细心程度的题) [样例解释]如果删去第一个 1:在[3,1,2]中有 3 个不同的数如果删去 3:在[1,1,2]中有 2 个不同的数如果删去第二个 1:在[ ...

  8. NOIP模拟 17.9.28

    公交车[问题描述]市内有

  9. Noip模拟17 2021.7.16

    我愿称这场考试为STL专练 T1 世界线 巧妙使用$bitset$当作vis数组使用,内存不会炸,操作还方便,的确是极好的. 但是这个题如果不开一半的$bitset$是会炸内存的,因为他能开得很大,但 ...

随机推荐

  1. 服务器重启,自动重启httpd

    1. 手动重启 cd http ll cd /etc/httpd/   ll service httpd restart 2. 查看服务器内存使用情况 df -h 3. 自动重启 cat /etc/i ...

  2. Windows的SEH机理简要介绍

    1.异常分类 一般来说,我们把Exception分为2类,一类是CPU产生的异常,我们称之为CPU异常(或者硬件异常).另一类为是通过调用RaiseException API产生的软件异常,我们称之为 ...

  3. 用python获取ip信息

    1.138网站 http://user.ip138.com/ip/首次注册后赠送1000次请求,API接口请求格式如下,必须要有token值 import httplib2 from urllib.p ...

  4. java基础温习 -- 多态

    1. 基本概念 多态是指一个事物有不同的表现形式或形态. 多态存在的三个必要条件:要有继承.要有重写.父类变量引用子类对象. 当使用多态方式调用方法时:         首先检查父类中是否有该方法,如 ...

  5. HtmlHelper2

    一.隐式从ViewBag取数据 1.action中的代码: ViewBag.UserName = "admin"; cshtml中的代码: @Html.TextBox(" ...

  6. spark生态圈简介

    原文引自:http://www.cnblogs.com/shishanyuan/p/4700615.html 1.简介 1.1 Spark简介 Spark是加州大学伯克利分校AMP实验室(Algori ...

  7. iOS开发系列-SQLite

    概述 SQLite3是一款轻型的嵌入式数据库.它占用资源非常低,在嵌入式设备中,可能只需要几百K的内存就够了.它的处理速度比Mysql.PostgreSQL这两款著名的数据库速度还快. 数据库简介 常 ...

  8. 2019-6-27-WPF-如何给定两个点画出一条波浪线

    title author date CreateTime categories WPF 如何给定两个点画出一条波浪线 lindexi 2019-6-27 10:17:6 +0800 2019-6-26 ...

  9. NCDC 天气数据的预处理

    "Hadoop: The Definitive Guild" 这本书的例子都是使用NCDC 天气数据的,但由于书的出版和现在已经有一段时间了,NCDC现在提供的原始数据结构已经有了 ...

  10. jiba中文分词原理

    中文分词就是将一个汉字序列分成一个一个单独的词. 现有的分词算法有三大类: 基于字符串匹配的分词:机械分词方法,它是按照一定的策略将待分析的字符串与一个充分大的机器词典中的词条进行匹配,若在词典中找到 ...