2021/3/21模拟赛

果然还是我太菜了

游戏(A)

【题目描述】

你得到了一个长度为N的整数数组A。现在希望你找到一对(i,j)满足i ≠ j,使 得( A i A_i Ai and A j A_j Aj) xor ( A i A_i Ai or A j A_j Aj)最小。

【输入格式】

第一行一个整数N。 第二行N个整数,表示数组A。 【输出格式】 一行一个整数,为这个最小值。

【数据范围】

Subtask 1 (40pts):N ≤ 1000。
Subtask 2 (20pts):所有数字相等。
Subtask 3 (40pts):无特殊限制。
对于全部数据:2 ≤ N ≤ 105 ∀1 ≤ i ≤ N,1 ≤ A i A_i Ai ≤ 1000000000。

#include<bits/stdc++.h>
using namespace std;
#define N 100010
int a[N],n,ans;
int read()
{
    
    
    int num=0;bool flag=1;
    char c=getchar();
    for(;c<'0'||c>'9';c=getchar())
      if(c=='-')flag=0;
    for(;c>='0'&&c<='9';c=getchar())
      num=(num<<1)+(num<<3)+c-'0';
    return flag?num:-num;
}
int main()
{
    
    
	ans=999999999;
	n=read();
	for(int i=1;i<=n;i++)
	{
    
    
		a[i]=read();
	}
	for(int i=1;i<=n;i++)
	{
    
    
		for(int j=1;j<=n;j++)
		{
    
    
			if(j==i) continue;
			if(ans>((a[i]&a[j])^(a[i]|a[j])))
			ans=min(ans,((a[i]&a[j])^(a[i]|a[j])));
		}
	}
	cout<<ans;
	return 0;
}

暴力60分算了在这里插入图片描述

在这里插入图片描述但是我转念一想,这个算式的话, a i a_i ai a j a_j aj交换下位置是不是还一样,这就能省掉一些不必要的步骤了
于是打了个表

#include<bits/stdc++.h>
using namespace std;
int a,b;
int main()
{
    
    
	while(1){
    
    cin>>a>>b;cout<<((a&b)^(a|b));puts("");swap(a,b);cout<<((a&b)^(a|b));}
}

为了能编译一次就多打出来点,我用 w h i l e ( 1 ) while(1) while(1)
然后一不小心发现了惊天大秘密——两数离得越近好像结果越小
于是就

#include<bits/stdc++.h>
using namespace std;
#define N 100010
long long a[N],n,ans,hh1,hh2;
long long read()
{
    
    
    long long num=0;bool flag=1;
    char c=getchar();
    for(;c<'0'||c>'9';c=getchar())
      if(c=='-')flag=0;
    for(;c>='0'&&c<='9';c=getchar())
      num=(num<<1)+(num<<3)+c-'0';
    return flag?num:-num;
}
int main()
{
    
    
	ans=99999999999999;
	n=read();
	for(long long i=1;i<=n;i++)
		a[i]=read();
	sort(a+1,a+1+n);
	for(long long i=1;i<n;i++)
	{
    
    
		long long j=i+1;
		ans=min(ans,((a[i]&a[j])^(a[i]|a[j])));
	}
	cout<<ans;
	return 0;
}

愉快地 A A A掉了
在这里插入图片描述
真正的题解

纸盒(B)

【题目描述】

现在用纸制作一个A × B × C的纸盒,将这个纸盒的六个面展开铺在一个平 面直角坐标系中的图形如下:
给出这个坐标系中的两点坐标( x 1 x_1 x1, y 1 y_1 y1),( x 2 x_2 x2, y 2 y_2 y2),保证这两点一定在纸盒的面 上,请你求出在折成纸盒之后这两点在空间中的直线距离(欧几里得距离)。

【输入格式】

第一行三个整数A,B,C。 接下来两行每行两个小数,分别为给出的两点坐标值xi,yi。

【输出格式】

输出一行一个小数,表示答案,答案四舍五入 ....至 2 位小数精度。

【数据范围】

Subtask 1 (20pts):保证给出两点在纸盒的同一面内。
Subtask 2 (20pts): A = B = C A=B=C A=B=C
Subtask 3 (30pts): A = B A=B A=B
Subtask 4 (30pts):无特殊限制。
对于全部数据: 0 < A , B , C ≤ 1 0 3 0<A,B,C≤10^3 0<A,B,C103
这题稍微学过一点立体几何的应该都会吧 在这里插入图片描述

在这里插入图片描述

#include<bits/stdc++.h>
using namespace std;
int main()
{
    
    
	double A,B,C;
	cin>>A>>B>>C;
	double a,b,c,d;
	cin>>a>>b>>c>>d;
	double x,y,h;
	if(a<C) x=C,y=b,h=C-a;
	else if(a>=C&&a<=A+C)
	{
    
    
		if(b<=B)x=a,y=B+C+B-b,h=C; 
		if(b>B&&b<B+C) x=a,y=C+B,h=y-b;
		if(b>=B+C&&b<=B+C+B) x=a,y=b,h=0;
		if(b>B+C+B&&b<=B+B+C+C)x=a,y=B+C+B,h=b-y;
	}
	else if(a>A+C) x=C+A,y=b,h=a-x;
	double xx=x,yy=y,hh=h;
	x=0,y=0,h=0;
	if(c<C)	x=C,y=d,h=C-c;
	else if(c>=C&&c<=A+C)
	{
    
    
		if(d<=B) x=c,y=B+C+B-d,h=C;
		if(d>B&&d<B+C) x=c,y=C+B,h=y-d;
		if(d>=B+C&&d<=B+C+B) x=c,y=d,h=0;
		if(d>B+C+B&&d<=B+B+C+C) x=c,y=B+C+B,h=d-y;
	}
	else if(c>A+C) x=C+A,y=d,h=c-x;
	double t=(xx-x)*(xx-x)+(yy-y)*(yy-y)+(hh-h)*(hh-h);
	cout<<sqrt(t);
	return 0;
}

但是这个题在样例方面存在问题,于是老师又给发了下样例,然后不小心把标程发了出来,这道题就不作数了。

反向(C)

【题目描述】

你在玩一个探险游戏。这个游戏中有一个地图,地图上有n个城市、m条道 路,每条道路将两个城市连通,且只能单向通行,通行花费的时间为1。单向的 道路使得你从起点S走到终点T需要花很多时间。 你得到了一个神秘的金手指,可以使地图中的任意一条道路的通行方向反 向,但金手指只能使用最多一次。你想知道金手指的作用有多大,因此,你需 要求出允许使用金手指的情况下从S到T的最短路长度。数据保证图中无自环、 无重边,且一定存在从S到T的路径。

【输入格式】

第一行两个整数n,m。
接下来m行,每行两个整数 u i u_i ui, v i v_i vi,表示地图中存在一条道路可以从城市 u i u_i ui走 向城市 v i v_i vi
最后一行两个整数S,T,表示起点和终点。

【输出格式】

输出一个数字表示答案。

【数据范围】

Subtask 1 (10pts):S = T。
Subtask 2 (30pts): 1 ≤ n ≤ 20 , 1 ≤ m ≤ 100 1≤n≤20,1≤m≤100 1n20,1m100
Subtask 3 (30pts):1 ≤ n,m ≤ 1 0 3 10^3 103
Subtask 4 (30pts):无特殊限制。
对于全部数据:1 ≤ n,m ≤ 1 0 5 10^5 105
在这里插入图片描述
堆优化的迪杰斯特拉显然很优秀,但是我不会,于是就用dfs水分

#include<bits/stdc++.h>
using namespace std;
int ans=99999999,s,t,n,m;
struct hhhc{
    
    
	int v,u;
}o[100086];
int read()
{
    
    
    int num=0;bool flag=1;
    char c=getchar();
    for(;c<'0'||c>'9';c=getchar())if(c=='-')flag=0;
    for(;c>='0'&&c<='9';c=getchar())num=(num<<1)+(num<<3)+c-'0';
    return flag?num:-num;
}
void dfs(int x,int y,int z)
{
    
    
	if(z>=ans)
		return;
	if(x==y)
	{
    
    
		ans=min(ans,z);
		return;
	}
	for(int i=1;i<=m;i++)
	{
    
    
		if(o[i].u==x)
		{
    
    
			dfs(o[i].v,y,z+1);
		}
	}
}
int main()
{
    
    
	n=read();m=read();
	for(int i=1;i<=m;i++)
	{
    
    
		o[i].u=read();o[i].v=read(); 
	}
	s=read();t=read();
	if(s==t)
	{
    
    
		cout<<'0';
		return 0;
	}
	for(int i=1;i<=m;i++)
	{
    
    
		swap(o[i].v,o[i].u);
		dfs(s,t,0);
		swap(o[i].v,o[i].u);
	}
	cout<<ans;
	return 0;
}

至今未解的是不知道为啥会MLE,而且不是全部MLE,就一个还不算太大的数据MLE了,真离谱啊。在这里插入图片描述

下面这个是正解代码

#include<bits/stdc++.h>
using namespace std;
const int maxn=1e5+10;
const long long INF=1e18;
int n,m,s,t,tot=0;
int head[maxn],vis[maxn][3],W[maxn];
long long dis[maxn][3];
struct Star
{
    
    
	int to,next;
}edge[2*maxn];
void Lian(int x,int y)
{
    
    
	tot++;
	edge[tot].to=y;
	edge[tot].next=head[x];
	head[x]=tot;
}
struct Point
{
    
    
	long long dd;
	bool f;
	int p;
	bool operator<(const Point &x) const{
    
    
		return dd>x.dd;
	}
};
vector <int> q[maxn];
void dijkstra(int s)
{
    
    
	priority_queue <Point> que;
	dis[s][0]=0;
	dis[s][1]=0;
	Point a;
	a.p=s;
	a.dd=0;
	a.f=0;
	que.push(a);
	while(!que.empty())
	{
    
    
		a=que.top();
		que.pop();
		int x=a.p;
		if(vis[x][a.f]) continue;
		else vis[x][a.f]=1;
		if(a.f==0)
		{
    
    
			for(int i=0;i<q[x].size();i++)
			{
    
    
				int y=q[x][i];
				if(dis[y][1]>dis[x][0]+1)
				{
    
    
					dis[y][1]=dis[x][0]+1;
					Point a1;
					a1.p=y;
					a1.dd=dis[y][1];
					a1.f=1;
					que.push(a1);
				}
			}
		}
		for(int i=head[x];i;i=edge[i].next)
		{
    
    
			int y=edge[i].to;
			Point a1;
			if(dis[y][a.f]>dis[x][a.f]+1)
			{
    
    
				
				dis[y][a.f]=dis[x][a.f]+1;
				a1.p=y;
				a1.dd=dis[y][a.f];
				a1.f=a.f;
				que.push(a1);
			}
		}
	}
}
int main()
{
    
    
	cin>>n>>m;
	for(int i=1;i<=m;i++)
	{
    
    
		int u,v,w;
		cin>>u>>v;
		Lian(u,v);
		q[v].push_back(u);
	}
	cin>>s>>t;
	if(s==t)
	{
    
    
		cout<<0;
		return 0;
	}
	for(int i=1;i<=n;i++) dis[i][0]=dis[i][1]=INF;
	dijkstra(s);
	cout<<min(dis[t][0],dis[t][1]);
	return 0;
}

租房(D)

【题目描述】

在港口有n间住宅,从1到n进行编号。有m家中介公司,第i家公司掌管着Li 到Ri的房子,收费为Ci元。某一个房子可能被多个公司掌管,当你租下这间房 子时,你需要给所有的中介付费。某个中介一旦已经向你收取过费用,那么他 们掌管的其他房子你就不必再向他们缴纳费用。 现在你希望在港口租下k间房供联盟的卫兵居住,请你求出最小消费。

【输入格式】

第一行三个整数n,m,k,意义如题。 接下来m行,每行三个整数,第i行的三个数分别代表 L i L_i Li, R i R_i Ri, C i C_i Ci

【输出格式】

一行一个整数,表示最小消费。

【数据范围】

Subtask 1 (10pts):输入数据为样例。
Subtask 2 (40pts):n,m,k ≤ 10。
Subtask 3 (50pts):无特殊限制。
对于全部数据:n,m,k ≤ 500 ∀1 ≤ i ≤ m,1 ≤ L i L_i Li R i R_i Ri ≤ n,1 ≤ C i C_i Ci ≤ 10000。
在这里插入图片描述
区间DP嘛,但是没时间了,于是输出了个样例,但是还是没骗到分
代码如下

#include<bits/stdc++.h>
using namespace std;
#define N 520
int n,m,k,l[N],r[N],c[N],b[N][N],sum[N][N],x,f[N][N],ans=999999999;
vector <int> t[N];
int main()
{
    
    
	memset(f,0x3f,sizeof(f));
	cin>>n>>m>>k;
	for(int i=1;i<=m;i++)
	{
    
    
		cin>>l[i]>>r[i]>>c[i];
		for(int j=l[i];j<=r[i];j++)
		{
    
    
			b[j][i]=1;
			t[j].push_back(i);
		}
	}
	for(int i=1;i<=n;i++)
		for(int j=0;j<i;j++)
			for(int w=0;w<t[i].size();w++)
			{
    
    
				x=t[i][w];
				if(!b[j][x])
					sum[i][j]+=c[x]; 
			}

	f[0][0]=0;
	for(int j=1;j<=k;j++)
		for(int i=j;i<=n;i++)
			for(int p=j-1;p<i;p++)
				if(t[i].size()>=1)
					f[i][j]=min(f[i][j],f[p][j-1]+sum[i][p]);
	for(int i=k;i<=n;i++)
		ans=min(ans,f[i][k]);
	cout<<ans;
	return 0;
}

本来还用了快读,但还是TLE,快读去掉就过了

猜你喜欢

转载自blog.csdn.net/ydsrwex/article/details/115053231