2017.8.15 校内模拟赛
题面及数据及std(有本人的也有原来的) :2017.8.15 校内模拟赛
8.15 解题报告
应得300,实得 275。
丢掉那25分的原因是有一个临时变量没开long long,而是int,然后运算过程爆了int,挂了25,mmp
T1 二分
T2 图论
T3 动态规划
1.第K小数 (number.cpp/c/pas)
【问题描述】
有两个正整数数列,元素个数分别为N和M。从两个数列中分别任取一个数 相乘,这样一共可以得到N*M个数,询问这N*M个数中第K小数是多少。
【输入格式】
输入文件名为number.in。
输入文件包含三行。
第一行为三个正整数N,M和K。
第二行为N个正整数,表示第一个数列。
第三行为M个正整数,表述第二个数列。
【输出格式】
输出文件名为number.out。
输出文件包含一行,一个正整数表示第K小数。
【输入输出样例1】
number.in
2 3 4
1 2
2 1 3
number.out
3
【输入输出样例2】
number.in
5 5 18
7 2 3 5 8
3 1 3 2 5
number.out
16
【数据规模与约定】
/* 二分第k小值 枚举检验 */ #include <algorithm> #include <iostream> #include <cstdio> #define Inline __attri\ bute__( ( optimize( "-O2" ) ) ) const int BUF = 100000010; char Buf[BUF], *buf = Buf; Inline void read (long long &now) { int temp = 0; for (now = 0; !isdigit (*buf); ++ buf) if (*buf == '-') temp = 1; for (; isdigit (*buf); now = now * 10 + *buf - '0', ++ buf); if (temp) now = -now; } #define Max 200010 long long a[Max], b[Max]; long long K, N, M; Inline bool Check (long long key) { long long pos = M, res = 0; for (int i = 1; i <= N; ++ i) { for (; pos && a[i] * b[pos] >= key; -- pos); res += pos; } return res >= K; } #define Judge Inline int Main () { #ifdef Judge freopen ("number.in", "r", stdin); freopen ("number.out", "w", stdout); fread (buf, 1, BUF, stdin); #endif read (N); read (M); read (K); register int i; for (i = 1; i <= N; ++ i) read (a[i]); for (i = 1; i <= M; ++ i) read (b[i]); std :: sort (a + 1, a + 1 + N); std :: sort (b + 1, b + 1 + M); long long l = 0, r = a[N] * b[M], Mid; long long Answer; for (; l <= r; ) { Mid = l + r >> 1; if (Check (Mid)) { Answer = Mid; r = Mid - 1; } else l = Mid + 1; } std :: cout << Answer - 1; fclose (stdin); fclose (stdout); return 0; } int ZlycerQan = Main (); int main (int argc, char *argv[]) {;};
2. dwarf tower (dwarf.cpp/c/pas)
【问题描述】
Vasya在玩一个叫做"Dwarf Tower"的游戏,这个游戏中有n个不同的物品, 它们的编号为1到n。现在Vasya想得到编号为1的物品。 获得一个物品有两种方式:
1. 直接购买该物品,第i件物品花费的钱为ci
2. 用两件其他物品合成所需的物品,一共有m种合成方式。
请帮助Vasya用最少的钱获得编号为1的物品。
【输入格式】
第一行有两个整数n,m(1<=n<=10000,0<=m<=100000),分别表示有n种物品以 及m种合成方式。
接下来一行有n个整数,第i个整数ci表示第i个物品的购买价格,其中 0<=ci<=10^9。
接下来m行,每行3个整数ai,xi,yi,表示用物品xi和yi可以合成物品ai,其 中(1<=ai,xi,yi<=n; ai<>xi, xi<>yi, yi<>ai)
【输出格式】
一行,一个整数表示获取物品 1 的最少花费。
输入样例:
5 3
5 0 1 2 5
5 2 3
4 2 3
1 4 5
输出样例:
2
【数据规模与约定】
60%的数据, n<=100
100%的数据, n<=10000, m<=100000
/* 把原题中的条件转成图论条件 即把能合成的物品连边 然后跑最短路就好了 */ #include <iostream> #include <cstring> #include <cstdio> #include <queue> #define Inline __attri\ bute__( ( optimize( "-O2" ) ) ) const int BUF = 100000010; char Buf[BUF], *buf = Buf; Inline void read (int &now) { for (now = 0; !isdigit (*buf); ++ buf); for (; isdigit (*buf); now = now * 10 + *buf - '0', ++ buf); } #define Max 10020 #define Judge int N, M; struct Edge { int to, next, w; }; class Spfa_Type { private : Edge e[Max * 10 * 3]; int list[Max], C; bool visit[Max]; int dis[Max]; public : Inline void Insert_edge (int u, int v, int z) { C ++; e[C].to = v; e[C].next = list[u]; list[u] = C; e[C].w = z; } Inline void Fill_Value (const int &N) { for (int i = 1; i <= N; ++ i) read (dis[i]); } Inline int Do_Spfa () { std :: queue <int> Queue; register int i; memset (visit, true, sizeof visit); for (i = 1; i <= N; ++ i) Queue.push (i); int now; for (; !Queue.empty (); Queue.pop ()) { now = Queue.front (); visit[now] = false; for (i = list[now]; i; i = e[i].next) if (dis[e[i].to] > dis[now] + dis[e[i].w]) { dis[e[i].to] = dis[now] + dis[e[i].w]; if (!visit[e[i].to]) { Queue.push (e[i].to); visit[e[i].to] = true; } } } return dis[1]; } }; Spfa_Type Make; Inline int Main () { #ifdef Judge freopen ("dwarf.in", "r", stdin); freopen ("dwarf.out", "w", stdout); fread (buf, 1, BUF, stdin); #endif read (N); read (M); register int i; Make.Fill_Value (N); int x, y, z; for (i = 1; i <= M; ++ i) { read (x), read (y), read (z); Make.Insert_edge (z, x, y); Make.Insert_edge (y, x, z); } printf ("%d", Make.Do_Spfa ()); fclose (stdin); fclose (stdout); return 0; } int ZlycerQan = Main (); int main (int argc, char *argv[]) {;}
3. abcd (abcd.cpp/c/pas)
【问题描述】
有4个长度为N的数组a,b,c,d。现在需要你选择N个数构成数组e,数组e满足 a[i]≤e[i]≤b[i]以及
并且使得最大。
【输入格式】
输入文件名为abcd.in。
输入文件共 N+1 行。
第 1 行包含1个正整数N。
第 i+1 行包含4个整数a[i],b[i],c[i],d[i]。
【输出格式】
输出文件名为abcd.out。
输出共1行,包含1个整数,表示所给出公式的最大值。
输入数据保证一定有 解。
【输入输出样例1】
abcd.in
5
- 1 1 2 5
-2 2 1 2
0 1 1 3
-2 -1 3 10
-2 2 3 9
abcd.out
2
【输入输出样例2】
abcd.in
10
1 10 1 7
-10 10 2 0
-10 10 2 2
-10 10 2 0
1 10 1 0
-10 10 2 0
10 10 2 0
1 10 1 0
-10 10 2 0
1 10 1 0
abcd.out
90
【输入输出样例3】
abcd.in
10
1 10 1 0
-10 10 2 2
-10 10 2 2
-10 10 2 2
1 10 1 0
-10 10 2 2
-10 10 2 2
1 10 1 0
-10 10 2 2
1 10 1 0
abcd.out
-4
【数据规模与约定】
对于 20%的数据, N≤10, -2≤a[i]<b[i]≤2;
对于 60%的数据, N≤50, -20≤a[i]<b[i]≤20;
对于 100%的数据, N≤200, -25≤a[i]<b[i]≤25, 1≤c[i]≤20, 0≤d[i] ≤10000
/* 考虑把原题转化为背包问题 根据a,b,c,d数组推出背包每个物品的cost与value 然后一遍01背包得解 */ #include <cstdio> #include <iostream> #include <cstring> #define Inline __attri\ bute__( ( optimize( "-O2" ) ) ) const int BUF = 100000010; char Buf[BUF], *buf = Buf; Inline void read (int &now) { int temp = 0; for (now = 0; !isdigit (*buf); ++ buf) if (*buf == '-') temp = 1; for (; isdigit (*buf); now = now * 10 + *buf - '0', ++ buf); if (temp) now = -now; } #define Max 200000 #define Judge int dp[Max]; int a[Max], b[Max], c[Max], d[Max]; Inline int max (int a, int b) { return a > b ? a : b; } int l[Max], value[Max], cost[Max]; int Answer; Inline int Main () { #ifdef Judge freopen ("abcd.in", "r", stdin); freopen ("abcd.out", "w", stdout); fread (buf, 1, BUF, stdin); #endif int N, M = 0; read (N); register int i, j; int Count = 0; for (i = 1; i <= N; ++ i) read (a[i]), read (b[i]), read (c[i]), read (d[i]); for (i = 1; i <= N; ++ i) { l[i] = b[i] - a[i]; M -= c[i] * a[i]; } for (i = 1; i <= N; ++ i) { Answer += a[i] * d[i]; for (j = 1; j <= l[i]; j <<= 1) { l[i] -= j, ++ Count; cost[Count] = c[i] * j; value[Count] = d[i] * j; } if (l[i]) { ++ Count; cost[Count] = c[i] * l[i]; value[Count] = d[i] * l[i]; } } memset (dp, -0x3f, sizeof dp); dp[0] = 0; for (i = 1; i <= Count; ++ i) for (j = M; j >= cost[i]; -- j) dp[j] = max (dp[j], dp[j - cost[i]] + value[i]); printf ("%d", Answer + dp[M]); fclose (stdin); fclose (stdout); return 0; } int ZlycerQan = Main (); int main (int argc, char *argv[]) {;}