果然还是我太菜了
游戏(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,C≤103。
这题稍微学过一点立体几何的应该都会吧
#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 1≤n≤20,1≤m≤100。
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,快读去掉就过了