• 2017.8.15 考试


    注:所有题目的时间限制均为 1s ,内存限制均为 256MB 。


    1 1 .第K K 小数
    ( ( number .cpp/c/pas)
    【问题描述】
    有两个正整数数列,元素个数分别为N和M。从两个数列中分别任取一个数
    相乘,这样一共可以得到N*M个数,询问这N*M个数中第K小数是多少。
    【输入格式】
    输入文件名为number.in。
    输入文件包含三行。
    第一行为三个正整数N,M和K。
    第二行为N个正整数,表示第一个数列。
    第三行为M个正整数,表述第二个数列。
    【输出格式】
    输出文件名为number.out。
    输出文件包含一行,一个正整数表示第K小数。
    【输入输出样例1 1 】
    number.in number.out
    2 3 4
    1 2
    2 1 3
    3
    【输入输出样例2 2 】
    number.in number.out
    5 5 18
    7 2 3 5 8
    3 1 3 2 5
    16
    【数据规模与约定】
    样例点编号 N M K 元素大小(≤)
    1 20 20 150 10^4
    2 50 50 2000 10^4
    3 100 80 5000 10^9
    4 200 200 26000 10^9
    5 10000 10000 50050000 10^4
    6 1000 20000 9500000 10^4
    7 1000 20000 10000500 10^9
    8 2000 20000 190000 10^9

    9 2000 20000 199000 10^9
    10 20000 20000 210005000 10^4
    11 20000 20000 210000 10^5
    12 20000 20000 200000 10^9
    13 20000 20000 220000500 10^5
    14 20000 20000 199000500 10^9
    15 200000 200000 180000 10^4
    16 200000 200000 200000 10^9
    17 2000 200000 100001500 10^9
    18 200000 180000 19550000000 10^5
    19 200000 200000 19900010000 10^9
    20 200000 200000 20000010000 10^9

    二分答案

    检验的时候,统计乘积<mid的数有多少个

    枚举a数组,b数组如果二分是O(log*logn*logm) 会T 4个点

    将a、b数组排序,那么随着a的递增,b中<mid的区间单调递减

    这样总复杂度O(log(n+m))

    #include<cstdio>
    #include<iostream>
    #include<algorithm>
    #define N 200001
    using namespace std;
    typedef long long LL;
    int n,m;
    LL k;
    int a[N],b[N];
    void read(int &x)
    {
        x=0; char c=getchar();
        while(!isdigit(c)) c=getchar();
        while(isdigit(c)) { x=x*10+c-'0'; c=getchar(); }
    }
    void read(LL &x)
    {
        x=0; char c=getchar();
        while(!isdigit(c)) c=getchar();
        while(isdigit(c)) { x=x*10+c-'0'; c=getchar(); }
    }
    bool check(LL mid)
    {
        int last=m;
        LL sum1=0;
        for(int i=1;i<=n;++i)
        {
            while(last) 
            if(1ll*a[i]*b[last]>=mid) last--;
            else break;
            sum1+=last;
        }
        if(sum1<k) return true; 
        return false;
    }
    void out(LL x)
    {
        if(x/10) out(x/10);
        putchar(x%10+'0');
    }
    int main()
    {
        freopen("number.in","r",stdin);
        freopen("number.out","w",stdout);
        read(n); read(m); read(k);
        for(int i=1;i<=n;i++) read(a[i]);
        for(int i=1;i<=m;i++) read(b[i]);
        sort(a+1,a+n+1);
        sort(b+1,b+m+1);
        LL l=1,r=1ll*a[n]*b[m],mid,ans;
        while(l<=r)
        {
            mid=l+r>>1;
            if(check(mid)) l=mid+1,ans=mid;
            else r=mid-1;
        }
        out(ans);
    }
    View Code

    2 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

    x和y可以合成a,x向a连边,y向a连边

    1——n 全部入队

    spfa

    #include<queue>
    #include<cstdio>
    #include<iostream>
    using namespace std;
    #define N 10001
    int cost[N],tot,head[N];
    bool vv[N];
    struct node
    {
        int to,nxt,with;
    }e[200001];
    queue<int>q;
    void read(int &x)
    {
        x=0; char c=getchar();
        while(!isdigit(c)) c=getchar();
        while(isdigit(c)) { x=x*10+c-'0'; c=getchar(); }
    }
    void add(int t,int u,int v)
    {
        e[++tot].to=t; e[tot].with=v; e[tot].nxt=head[u]; head[u]=tot;
        e[++tot].to=t; e[tot].with=u; e[tot].nxt=head[v]; head[v]=tot;
    }
    int main()
    {
        freopen("dwarf.in","r",stdin);
        freopen("dwarf.out","w",stdout);
        int n,m,a,b,c;
        read(n); read(m);
        for(int i=1;i<=n;++i) read(cost[i]);
        for(int i=1;i<=m;i++) 
        {
            read(a),read(b),read(c);
            add(a,b,c);
        }
        for(int i=1;i<=n;i++) q.push(i);
        int now;
        while(!q.empty())
        {
            now=q.front(); q.pop(); vv[now]=false;
            for(int i=head[now];i;i=e[i].nxt)
             if(cost[e[i].to]>cost[now]+cost[e[i].with])
             {
                 cost[e[i].to]=cost[now]+cost[e[i].with];
                 if(!vv[e[i].to]) vv[e[i].to]=true,q.push(e[i].to);
             }
        }
        printf("%d",cost[1]);
    }
    View Code

    3 . abcd
    (abcd.cpp/c/pas)
    【问题描述】
    有4个长度为N的数组a,b,c,d。现在需要你选择N个数构成数组e,数组e满足
    a[i]≤e[i]≤b[i]以及

    N

    Σ  e i ∗ c[i]  =0
    i=1

    并且使得

    N

    Σ  e i ∗ d[i]
    i=1
    最大。
    【输入格式】
    输入文件名为abcd.in。
    输入文件共 N+1 行。
    第 1 行包含1个正整数N。
    第 i+1 行包含4个整数a[i],b[i],c[i],d[i]。
    【输出格式】
    输出文件名为abcd.out。
    输出共1行,包含1个整数,表示所给出公式的最大值。输入数据保证一定有
    解。
    【输入输出样例1 1 】
    abcd.in abcd.out
    5
    -1 1 2 5
    -2 2 1 2
    0 1 1 3
    -2 -1 3 10
    -2 2 3 9
    2
    【输入输出样例2 2 】
    abcd.in abcd.out
    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
    90
    10 10 2 0
    1 10 1 0
    -10 10 2 0
    1 10 1 0
    【输入输出样例3 3 】
    abcd.in abcd.out
    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
    -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

    背包问题

    c为体积,d为价值,每件物品有a——b件,选e件,填满一个体积为0的背包

    两个问题:

    1、a可能为负数

    2、背包体积不能为0

    所以

    1、件数由a——b,转化为0——b-a,这样选e件相当于选e-a件

    2、根据等式,左边是e件,实际选了e-a件,所以右边也要减去a*c,所以背包体积为 Σ-a[i]*c[i]

    答案就是 Σ(e[i]-a[i])*d[i] + Σ a[i]*d[i]

    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    #define N 201
    using namespace std;
    int a[N],b[N],c[N],d[N];
    int num[N],v[N*N],w[N*N],f[N*500];
    int tot,ans,n,m;
    void read(int &x)
    {
        x=0; int f=1; char c=getchar();
        while(!isdigit(c)) { if(c=='-') f=-1; c=getchar();}
        while(isdigit(c)) { x=x*10+c-'0'; c=getchar(); }
        x*=f;
    }
    void add(int k,int sum)
    {
        v[++tot]=c[k]; w[tot]=d[k];
        int i=1;  sum--;
        while(sum-i*2>=0)
        {
            sum-=i*2;
            v[++tot]=i*2*c[k];
            w[tot]=i*2*d[k];
            i*=2;
        }
        if(sum) 
        {
            v[++tot]=sum*c[k];
            w[tot]=sum*d[k];
        }
    }
    int main()
    {
        freopen("abcd.in","r",stdin);
        freopen("abcd.out","w",stdout);
        scanf("%d",&n);
        for(int i=1;i<=n;i++) 
        {
            scanf("%d%d%d%d",&a[i],&b[i],&c[i],&d[i]);
            num[i]=b[i]-a[i];
            ans+=a[i]*d[i];
            add(i,num[i]);
            m+=-a[i]*c[i];
        }
        memset(f,-0x3f3f3f,sizeof(f));
        f[0]=0;
        for(int i=1;i<=tot;i++)
         for(int j=m;j>=v[i];j--)
          f[j]=max(f[j],f[j-v[i]]+w[i]);
        printf("%d",f[m]+ans);
    }
    View Code
  • 相关阅读:
    pypy异步gRPC实现
    redis常用操作
    Linux挂载命令mount用法及参数详解
    nginx 做负载均衡反向代理
    Minio部署
    增加nginx虚拟主机配置文件(conf.d)
    nginx 部署后端项目
    Flask从入门到精通
    Scrapy
    4操作Redis之redigo
  • 原文地址:https://www.cnblogs.com/TheRoadToTheGold/p/7380314.html
Copyright © 2020-2023  润新知