• 套题 8.22


    注:所有题目的时间限制均为 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

    二分,

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<queue>
    #include<cstring>
    #include<vector>
    #include<math.h>
    using namespace std;
    unsigned long long a[200009],b[200009],n,m,k;
    bool check(unsigned long long mid)
    {
        unsigned long long tot=0,L=1,R=m;
        while(L<=n&&R>=1)
        {
            while(a[L]*b[R] > mid )    R--;
            tot+=R;
            L++;
        }    
        return tot<k;
    }
    int main()
    {
        freopen("number.in","r",stdin);
        freopen("number.out","w",stdout);
        scanf("%lld%lld%lld",&n,&m,&k);
        for(int i=1;i<=n;i++)    scanf("%lld",&a[i]);
        for(int i=1;i<=m;i++)    scanf("%lld",&b[i]);
        
        sort(a+1,a+1+n); sort(b+1,b+1+m);
        
        unsigned long long l=0,r=a[n]*b[m];
        while(l<r)
        {
            unsigned long long mid=(l+r)>>1;
            if(check(mid))    l=mid+1;
            else r=mid;
        }
        cout<<l;
        return 0;
    }
    代码


    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

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<queue>
    #include<cstring>
    #include<vector>
    #include<math.h>
    using namespace std;
    int n,m;
    struct node{
        int a,y,nex;
    }a[200009];
    long long  c[10009];
    int cnt,h[10009];
    bool vis[10009];
    void add(int x,int y,int f)
    {
        ++cnt;
        a[cnt].y=y;
        a[cnt].a=f;
        a[cnt].nex=h[x];
        h[x]=cnt;
    }
    void spfa()
    {
        queue<int>q;
        long long xx;
        for(int i=1;i<=n;i++)
        {q.push(i);vis[i]=1;}
        while(!q.empty())
        {
            xx=q.front();vis[xx]=0;q.pop();
            for(int i=h[xx];i;i=a[i].nex)
            {
                if(c[xx]+c[a[i].y] < c[a[i].a])
                {
                     c[a[i].a]=c[xx]+c[a[i].y];
                    if(!vis[a[i].a])
                    {
                        q.push(a[i].a);
                        vis[a[i].a]=1;
                    }
                }
            }
        }
    }
    int main()
    {
        freopen("dwarf.in","r",stdin);
        freopen("dwarf.out","w",stdout);
        scanf("%d%d",&n,&m);
        
        for(int i=1;i<=n;i++)
        scanf("%lld",c+i);
        
        for(int i=1,a,x,y;i<=m;i++)
        {
            scanf("%d%d%d",&a,&x,&y);        
            add(x,y,a);
            add(y,x,a);
        }
        spfa();
        cout<<c[1];
        return 0;
    }


    3 3 . abcd
    (abcd.cpp/c/pas)
    【问题描述】
    有4个长度为N的数组a,b,c,d。现在需要你选择N个数构成数组e,数组e满足
    a[i]≤e[i]≤b[i]以及
    e i ∗ c[i]
    N
    i=1
    = 0
    并且使得
    e i ∗ d[i]
    N
    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

    多重背包

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<queue>
    #include<cstring>
    #include<vector>
    #include<math.h>
    #include<ctime>
    using namespace std;
    int a[300],b[300],c[300],d[300],e[300];
    int sum[300],v[3000],w[3000],cnt;
    int f[400000],n;
    long long ans=0,m=0;
    void add(int k,int sum)
    {
        v[++cnt]=c[k],w[cnt]=d[k];
        int i=1;sum--;
        while(sum-i*2>=0)
        {
            sum-=i*2;
            v[++cnt]=c[k]*i*2;
            w[cnt]=d[k]*i*2;
            i=i*2;
        }
        if(sum)
        {
            v[++cnt]=sum*c[k];
            w[cnt]=sum*d[k];
        }
        return ;
    }
    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]);
            sum[i]=b[i]-a[i];
            ans+=a[i]*d[i];        
            add(i,sum[i]);
            m+=-a[i]*c[i];
        }
        memset(f,-0x3f3f3f,sizeof(f));    
        
        f[0]=0;
        for(int i=1;i<=cnt;i++)
        for(int j=m;j>=v[i];j--)
            f[j]=max(f[j],f[j-v[i]]+w[i]);
        cout<<(f[m]+ans);
        return 0;
    }
  • 相关阅读:
    交易之道
    走出幻觉,走向成熟(阅读心得一)
    爱由心生
    正则资料整理(转载)
    需要学习的.NET技术(转载)
    抽象类与接口的区别
    心存感激
    MYSQL 远程访问被限制
    PHP积累
    Git积累
  • 原文地址:https://www.cnblogs.com/CLGYPYJ/p/7410406.html
Copyright © 2020-2023  润新知