您的位置:首页 > 其它

2017.8.15 校内模拟赛

2017-08-17 11:34 239 查看
题面及数据及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
* 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<=100100%的数据, 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[]) {;}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: