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)

【问题描述】

有两个正整数数列,元素个数分别为NM。从两个数列中分别任取一个数 相乘,这样一共可以得到N*M个数,询问这N*M个数中第K小数是多少。

【输入格式】

输入文件名为number.in

输入文件包含三行。

第一行为三个正整数N,MK

第二行为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[]) {;};

 

 

 

 

 

 

2dwarf tower (dwarf.cpp/c/pas)

【问题描述】

Vasya在玩一个叫做"Dwarf Tower"的游戏,这个游戏中有n个不同的物品, 它们的编号为1n。现在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,表示用物品xiyi可以合成物品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<=10000m<=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[]) {;}

 

 

 

 

 

3abcd (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]≤251≤c[i]≤200≤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[]) {;}

 

 

posted @ 2017-08-17 11:34  ZlycerQan  阅读(286)  评论(0编辑  收藏  举报