8.15 Test Problem Solution.

1.第K小数(number.cpp/c/pas)

题目描述

有两个正整数数列,元素个数分别为N和M。从两个数列中分别任取一个数

相乘,这样一共可以得到N*M个数,询问这N*M个数中第K小数是多少。

输入输出格式

输入格式:

输入文件名为number.in。

输入文件包含三行。

第一行为三个正整数N,M和K。

第二行为N个正整数,表示第一个数列。

第三行为M个正整数,表述第二个数列。

输出格式:

输出文件名为number.out。

输出文件包括一行,一个正整数表示第k小数。

输入输出样例

输入样例#1:

2 3 4
1 2
2 1 3

输出样例#1:

3

输入样例#2:

5 5 18
7 2 3 5 8
3 1 3 2 5

输出样例#2:

16

说明

1<=n,m<=200000,1<=k<=20000010000,数列元素<=10^9;

test的时候好不容易想到了二分,结果犯了几个sb错误,sort写错了,Judge函数参数传错了,还好没有爆零得了25分,GG。

两个数列(a,b)sort之后,a[i]*b[1-m]是满足单调性的,b[i]*a[1-n]也是满足单调性的,所以可以二分。

25分BUG-Code:

#include<cstdio>
#include<iostream>
#include<algorithm>
using namespace std;
typedef long long ll;
#define maxn 200010
#define maxm 200010
ll a[maxn],b[maxm],k;
int n,m;
inline void input(ll &x) {
    x=0;
    ll a=1;char c=getchar();
    for(;c<‘0‘||c>‘9‘;c=getchar())
        if(c==‘-‘) a=-1;
    for(;c>=‘0‘&&c<=‘9‘;c=getchar())
        x=x*10+c-‘0‘;
    return;
}
inline void read(int &x) {
    x=0;
    int a=1;char c=getchar();
    for(;c<‘0‘||c>‘9‘;c=getchar())
        if(c==‘-‘) a=-1;
    for(;c>=‘0‘&&c<=‘9‘;c=getchar())
        x=x*10+c-‘0‘;
    return;
}
inline bool judge(int x) {
    ll rank=0;
    for(int i=1,j=m;i<=n;++i,rank+=(ll)j)
        while(j>=1&&a[i]*b[j]>x) j--;
    return rank<k?false:true;
}
int main() {
    read(n),read(m),input(k);
    for(int i=1;i<=n;++i) input(a[i]);
    for(int i=1;i<=m;++i) input(b[i]);
    sort(a+1,a+n+1);
    sort(b+1,b+n+1);
    ll l=0,r=a[n]*b[m],mid,ans;
    while(l<=r) {
        mid=l+r>>1;
        if(judge(mid)) {
            r=mid-1;
            ans=mid;
        } else l=mid+1;
    }
    cout<<ans;
    return 0;
}

  Judge参数改为ll,sort b数组改为b+m+1就可以A,mdzz;

#include<cstdio>
#include<iostream>
#include<algorithm>
using namespace std;
typedef long long ll;
#define maxn 200010
#define maxm 200010
ll a[maxn],b[maxm],k;
int n,m;
inline void input(ll &x) {
    x=0;
    ll a=1;char c=getchar();
    for(;c<‘0‘||c>‘9‘;c=getchar())
        if(c==‘-‘) a=-1;
    for(;c>=‘0‘&&c<=‘9‘;c=getchar())
        x=x*10+c-‘0‘;
    return;
}
inline void read(int &x) {
    x=0;
    int a=1;char c=getchar();
    for(;c<‘0‘||c>‘9‘;c=getchar())
        if(c==‘-‘) a=-1;
    for(;c>=‘0‘&&c<=‘9‘;c=getchar())
        x=x*10+c-‘0‘;
    return;
}
inline bool judge(ll x) {
    ll rank=0,j=m;
    for(int i=1;i<=n;++i,rank+=j)
        while(j>=1&&a[i]*b[j]>x) j--;
    return rank<k?false:true;
}
int main() {
    read(n),read(m),input(k);
    for(int i=1;i<=n;++i) input(a[i]);
    for(int i=1;i<=m;++i) input(b[i]);
    sort(a+1,a+n+1);
    sort(b+1,b+m+1);
    ll l=0,r=a[n]*b[m],mid,ans;
    while(l<=r) {
        mid=l+r>>1;
        if(judge(mid)) {
            r=mid-1;
            ans=mid;
        } else l=mid+1;
    }
    cout<<ans;
    return 0;
}

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 的最少花费。

输入输出样例

输入样例#1:

5 3
5 0 1 2 5
5 2 3
4 2 3
1 4 5

输出样例#1:

2

说明

60%的数据,n<=100

100%的数据,n<=10000,m<=100000

T2一看上去就比较简单,自己手画了一下,感觉可以直接可以边读入边更新,最后输出w[1]就好了。不过很快我就发现了这个算法的缺陷,如果一个物品A能通过合成两个物品来减小费用,那么以前这个A更新过的费用就不是最小的,GG。苦思冥想最后想出来了一种类似于spfa的bfs的做法,开一个struct,记录x和y可以合成a,还有就是类似于存边的next和head,一开始先把所有物品push进队列里,确保每个物品都会更新,其余的就是类似于spfa的操作,这貌似是正解,本来可以A,可惜我TM入队入错了GG,还好数据水,得了40分。

40分BUG-Code

#include<queue>
#include<cstdio>
#include<algorithm>
using namespace std;
#define maxn 10010
#define maxm 100010
struct woyaoac {//忽略掉这个结构体名
    int x,y,a,next;
    woyaoac(int x=0,int y=0,int a=0,int next=0):
        x(x),y(y),a(a),next(next) {}
}A[maxm<<1];
int cnt,w[maxn],head[maxn],n,m;
bool notinq[maxn]={0};
queue<int>q;
inline int input() {
    int x=0,a=1;char c=getchar();
    for(;c<‘0‘||c>‘9‘;c=getchar())
        if(c==‘-‘) a=-1;
    for(;c>=‘0‘&&c<=‘9‘;c=getchar())
        x=x*10+c-‘0‘;
    return x*a;
}
inline void add(int x,int y,int a) {
    A[++cnt]=woyaoac(x,y,a,head[x]);
    head[x]=cnt;
    return;
}
int lpfa() {//忽略掉这个函数名
    for(int i=1;i<=n;i++) q.push(i);
    while(!q.empty()) {
        int x=q.front();
        q.pop();
        notinq[x]=true;
        for(int i=head[x];i;i=A[i].next) {
            int y=A[i].y,a=A[i].a;
            if(w[x]+w[y]<w[a]) {
                w[a]=w[x]+w[y];
                if(notinq[y]==true) {
                    q.push(y);
                    notinq[y]=false;
                }
            }
        }
    }
    return w[1];
}
int main() {
    n=input(),m=input();
    for(int i=1;i<=n;i++) w[i]=input();
    for(int i=1;i<=m;i++) {
        int a=input(),x=input(),y=input();
        add(x,y,a);
        add(y,x,a);
    }
    printf("%d",lpfa());
    return 0;
}

看到那个if(notinq[])了吗?把y改成a就A了,GG。

#include<queue>
#include<cstdio>
#include<algorithm>
using namespace std;
#define maxn 10010
#define maxm 100010
struct woyaoac {
    int x,y,a,next;
    woyaoac(int x=0,int y=0,int a=0,int next=0):
        x(x),y(y),a(a),next(next) {}
}A[maxm<<1];
int cnt,w[maxn],head[maxn],n,m;
bool notinq[maxn]={0};
queue<int>q;
inline int input() {
    int x=0,a=1;char c=getchar();
    for(;c<‘0‘||c>‘9‘;c=getchar())
        if(c==‘-‘) a=-1;
    for(;c>=‘0‘&&c<=‘9‘;c=getchar())
        x=x*10+c-‘0‘;
    return x*a;
}
inline void add(int x,int y,int a) {
    A[++cnt]=woyaoac(x,y,a,head[x]);
    head[x]=cnt;
    return;
}
int lpfa() {
    for(int i=1;i<=n;i++) q.push(i);
    while(!q.empty()) {
        int x=q.front();
        q.pop();
        notinq[x]=true;
        for(int i=head[x];i;i=A[i].next) {
            int y=A[i].y,a=A[i].a;
            if(w[x]+w[y]<w[a]) {
                w[a]=w[x]+w[y];
                if(notinq[a]==true) {
                    q.push(a);
                    notinq[a]=false;
                }
            }
        }
    }
    return w[1];
}
int main() {
    n=input(),m=input();
    for(int i=1;i<=n;i++) w[i]=input();
    for(int i=1;i<=m;i++) {
        int a=input(),x=input(),y=input();
        add(x,y,a);
        add(y,x,a);
    }
    printf("%d",lpfa());
    return 0;
}

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:

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

输出样例#1:

-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

人生第一道玄学DFS+卡时。稳稳当当的20分。

或许你可以学到卡时QAQ

#include<ctime>
#include<cstdio>
#include<algorithm>
using namespace std;
#define maxn 210
#define inf 0x7fffffff
int a[maxn],b[maxn],c[maxn],d[maxn];
int e[maxn],Ans=-inf,n,T;
inline int input() {
	int x=0,a=1;char c=getchar();
	for(;c<‘0‘||c>‘9‘;c=getchar())
		if(c==‘-‘) a=-1;
	for(;c>=‘0‘&&c<=‘9‘;c=getchar())
		x=x*10+c-‘0‘;
	return x*a;
}
void dfs(int x,int ans) {
	if(clock()-T>=900) {
		printf("%d",Ans);
		exit(0);
	}
	if(x==n+1) {
		int sum=0;
		for(int i=1;i<=n;i++) sum+=e[i]*c[i];
		if(sum==0) Ans=max(Ans,ans);
		else return;
	} else for(int i=a[x];i<=b[x];i++) {
		int t=e[x];
		e[x]=i;
		dfs(x+1,ans+e[x]*d[x]);
		e[x]=t;
	}
	return;
}
int main() {
	T=clock();
	n=input();
	for(int i=1;i<=n;i++)
		a[i]=input(),b[i]=input(),c[i]=input(),d[i]=input();
	dfs(1,0);
	printf("%d",Ans);
	return 0;
}

正解是多重背包。GG。

∑e[i]*c[i]=0 和 ans=∑b[i]*e[i]
因为e[i]=[a[i],b[i]]等价于[0,b[i]-a[i]]+a[i];
问题转化为使得 ∑(b[i]-a[i])*c[i]+∑a[i]*c[i]=0 且∑(b[i]-a[i])*d[i]+∑a[i]*d[i]最大.
∑a[i]*c[i]和∑a[i]*d[i]是可以计算的.
令V=∑a[i]*c[i](V<0),s[i]=b[i]-a[i].
问题转化为在体积为-V的背包中取物品s[i]求最大值. 可以二进制拆01背包.GG

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define maxn 210
#define maxm 100010
int a[maxn],b[maxn],c[maxn],d[maxn];
int dp[maxm],w[maxm],v[maxm];
int ans,V,cnt;
inline int input() {
    int x=0,a=1;char c=getchar();
    for(;c<‘0‘||c>‘9‘;c=getchar())
        if(c==‘-‘) a=-1;
    for(;c>=‘0‘&&c<=‘9‘;c=getchar())
        x=x*10+c-‘0‘;
    return x*a;
}
int main() {
    int n=input();
    for(int i=1;i<=n;i++) {
        a[i]=input(),b[i]=input(),c[i]=input(),d[i]=input();
        V+=a[i]*c[i];
        b[i]-=a[i];
        ans+=a[i]*d[i];
    }
    for(int i=1;i<=n;i++) {
        for(int j=1;j<=b[i];j<<=1) {
            b[i]-=j;
            w[++cnt]=d[i]*j;
            v[cnt]=c[i]*j;
        }
        if(b[i]) {
            w[++cnt]=d[i]*b[i];
            v[cnt]=c[i]*b[i];
        }
    }
    memset(dp,-127/3,sizeof(dp));//神TM的127
    dp[0]=0,V*=-1;
    for(int i=1;i<=cnt;i++)
        for(int j=V;j>=v[i];j--)
            dp[j]=max(dp[j],dp[j-v[i]]+w[i]);
    ans+=dp[V];
    printf("%d",ans);
    return 0;
}

  

本来是100+100+20=220,结果最后25+40+20=GG。

神TM的sort,神TM的lpfa.

时间: 2024-10-06 03:44:56

8.15 Test Problem Solution.的相关文章

Lintcode1 A+B Problem solution 题解

[题目描述] Write a function that add two numbers A and B. You should not use + or any arithmetic operators. Notice:There is no need to read data from standard input stream. Both parameters are given in function aplusb, you job is to calculate the sum and

Problem D UVA 10608

Problem I FRIENDS There is a town with N citizens. It is known that some pairs of people are friends. According to the famous saying that ?The friends of my friends are my friends, too? it follows that if A and B are friends and B and C are friends t

tomcat(15)Digester库

[0]README 0.1)本文部分文字描述转自 "how tomcat works",旨在学习 "tomcat(15)Digester库" 的基础知识: 2)problem+solution: 2.1)problem:如下面的代码,Bootstrap类实例化连接器,servlet容器,Wrapper容器和其它组件,如设置连接器的关联顶层容器,通过set方法将它们联系起来:如监听器组件通过addLifecycleListener来设置等等.这种配置应用程序的方法有一

「Luogu2522」[HAOI2011]Problem b

「Luogu2522」[HAOI2011]Problem b problem Solution 题目要求 \[\sum_{x=a}^b\sum_{y=c}^d[gcd(x,y)=k]\] 设上式为\(Ans(a,b,c,d,k)\) 不妨来想一想\(a=1,c=1\)的时候怎么做 其实就跟「Luogu3455」[POI2007]ZAP-Queries一模一样了 略过一大堆式子,当\(a=c=1\)时 \[Ans(1,b,1,d,k)=\sum_{t=1}^{\frac{min(b,d)}{k}}

编译Busybox时,出现错误fatal error: curses.h: No such file or directory

1 scripts/kconfig/mconf.c: In function ‘exec_conf’: 2 scripts/kconfig/mconf.c:481:2: warning: ignoring return value of ‘pipe’, declared with attribute warn_unused_result [-Wunused-result] 3 pipe(pipefd); 4 ^ 5 SHIPPED scripts/kconfig/zconf.tab.c 6 SH

Java Interview Reference Guide--reference

Part 1 http://techmytalk.com/2014/01/24/java-interview-reference-guide-part-1/ Posted on January 24, 2014 by Nitin Kumar JAVA Object Oriented Concepts Java in based on Object Oriented concepts, which permits higher level of abstraction to solve any p

computer repair services in Hangzhou

We provide support for all kinds of Windows based Desktops and Laptops all over Hangzhou,I will be in a very short period of time drove up. 24hr cellphone: 13989897876 (James) QQ:305959965 Wechat: 13989897876Goutingba 37 , No 216 Shenbanlu RD(s), Gon

【LeetCode】9 - Palindrome Number

Determine whether an integer is a palindrome. Do this without extra space. Some hints: Could negative integers be palindromes? (ie, -1) If you are thinking of converting the integer to string, note the restriction of using extra space. You could also

HTK训练错误消息意义

在HTK训练线上数据的时候,遇到了ERROR [+6550] LoadHTKLabels: Junk at end of HTK transcription,这个问题,网上查阅是说有空行,结果根本没有空行,最后查找可知,是标注文件lab里面有空格,转成lab.mlf文件后,空格单独成一行,所以造成了这个小困扰. 定位问题之后,就很好解决了: sed -i 's/\s//g' *char.mlf sed -i '/^$/d' *char.mlf 以下是网上找的错误消息的意义,以供后续参考. UND