2021年度训练联盟热身训练赛第一场
文章目录
- D.Some Sum
- 题意:
- 题解:
- 代码:
- F.Pulling Their Weight
- 题意:
- 题解:
- 代码:
- H On Average They're Purple
- 题意:
- 题解:
- 代码:
- J This Ain't Your Grandpa's Checkerboard
- 题意:
- 题解:
- 代码:
题号 | 题目 | 通过率 | 知识点 |
---|---|---|---|
A | Weird Flecks, But OK | 667/1259 | 最小圆覆盖 |
B | Code Names | 450/1433 | |
C | New Maths | 348/856 | |
D | Some Sum | 1522/3277 | |
E | Early Orders | 688/2891 | |
F | Pulling Their Weight | 1124/2532 | |
G (未解决) | Birthday Paradox | 162/386 | |
H | On Average They’re Purple | 948/2167 | |
I (未解决) | Full Depth Morning Show | 212/341 | |
J | This Ain’t Your Grandpa’s Checkerboard | 1352/1867 | |
K(未解决) | Solar Energy | 102/812 |
D.Some Sum
题意:
你的朋友偷偷地选了N个介于1和100之间的连续的整数,并希望您猜测它们的和是否为偶数或奇数。
如果总和必须是偶数,则输出 even ;
如果总和必须是奇数,则输出 odd ;
如果和可以是偶数也可以是奇数,输出 Either 。
题解:
枚举出规律
当N=1时,可能为偶数也可能为奇数
当N=2时,两个连续的数的和,那么一定是奇数+偶数,奇数+偶数一定等于奇数
当N=3时,可能为偶数也可能为奇数
当N=4时,一定是偶数
当N=5时,可能为偶数也可能为奇数
当N=6时,一定是奇数
当N=7时,可能为偶数也可能为奇数
当N=8时,一定是奇数
当N=9时,可能为偶数也可能为奇数
当N=10时,一定是偶数
总结:
N是奇数,什么都有可能
N是偶数,如果n/2还是偶数,结果就是偶数
N是偶数,如果n/2还是奇数,结果就是奇数
代码:
#include <iostream>
using namespace std;
int main()
{int n;cin>>n;if(n%2!=0) //如果输入的n是奇数,那么得到的和可能为奇数也可能为偶数cout<<"Either";else //如果输入的n是偶数{if(n/2%2==0) //如果 偶数/2 还是偶数,那么结果一定为偶数cout<<"Even";else //如果 偶数/2 为奇数,那么结果一定为奇数cout<<"Odd";}return 0;}
F.Pulling Their Weight
题意:
n个数,让你选一个t,然后比t小的放一侧,比t大的放一侧,要求两侧一样大,问t最小是多少?
(如果和t一样大,奇数个就丢掉一个,剩下偶数个平分,偶数个就直接平分)
题解:
预处理前缀和
我想的二分,二分mid,然后用lower_bound(a+1,a+1+n,mid)来找第一个大于等于mid的数的位置,然后判断前后的和是否一样,和t一样大的数我们不需要考虑,因为他要么被抛弃,要么平分,没有影响
详细看代码吧
代码:
/*
7
3
6
4
4
4
1
2
*/#include<bits/stdc++.h>
typedef long long ll;
using namespace std;
inline int read(){int s=0,w=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}while(ch>='0'&&ch<='9') s=s*10+ch-'0',ch=getchar();//s=(s<<3)+(s<<1)+(ch^48);return s*w;
}
const int maxn=1e5+9;
int a[maxn];
int ch[2*maxn];
int n;
int sum[maxn];
int check(int mid)
{int w=lower_bound(a+1,a+1+n,mid)-a;int pos1;pos1=w-1;int pos2=w+ch[mid]-1;if((sum[pos1])>=(sum[n]-sum[pos2]))return 1;return 0;
}
int main()
{cin>>n;int tot=0;for(int i=1;i<=n;i++){cin>>a[i];ch[a[i]]++;}bool f=1;for(int i=2;i<=n;i++){if(a[1]!=a[i]){f=0;} }if(f==1){cout<<a[1]<<endl;return 0;}sort(a+1,a+n+1);for(int i=1;i<=n;i++)sum[i]=sum[i-1]+a[i];int l=0,r=2e4+9;while(l<r){int mid=(l+r)>>1;if(check(mid))r=mid;else l=mid+1;}cout<<l;
}
H On Average They’re Purple
题意:
我们首先规定,如果两个边有公共点,且两边是不一样的颜色,如果从一个边走到另一个边,我们称之为“颜色变换”
给你一个图,n个点,m条边,A要从1走到n点,B要给m个边染色,B想要A尽可能走颜色变换,A会尽可能少走“颜色变化”,输出A最少走多少?
(一共就两个颜色)
题解:
因为一共就两个颜色,所以B想要A走更多的颜色变换就是两个颜色交替走,A要走最少其实就是走最短路,B给最短路染色,所以答案就是1到n的最短路减1
直接套最短路模板
代码:
#include<bits/stdc++.h>
using namespace std;
#define maxn 300005
#define maxm 500005
#define INF 1234567890
inline int read()
{int x=0,k=1; char c=getchar();while(c<'0'||c>'9'){if(c=='-')k=-1;c=getchar();}while(c>='0'&&c<='9')x=(x<<3)+(x<<1)+(c^48),c=getchar();return x*k;
}
struct Edge
{int u,v,w,next;
}e[maxm];
int head[maxn],cnt,n,m,s,vis[maxn],dis[maxn],pre[maxn];
struct node
{int w,now;inline bool operator <(const node &x)const//重载运算符把最小的元素放在堆顶(大根堆){return w>x.w;//这里注意符号要为'>'}
};
priority_queue<node>q;
//优先队列,其实这里一般使用一个pair,但为了方便理解所以用的结构体
inline void add(int u,int v,int w)
{e[++cnt].u=u;//这句话对于此题不需要,但在缩点之类的问题还是有用的e[cnt].v=v;e[cnt].w=w;e[cnt].next=head[u];//存储该点的下一条边head[u]=cnt;//更新目前该点的最后一条边(就是这一条边)
}
//链式前向星加边void print(int x)
{if(pre[x]==0)return ;print(pre[x]);cout<<"-> "<<x;
}
void dijkstra()
{for(int i=1;i<=n;i++){dis[i]=INF;}dis[s]=0;//赋初值q.push((node){0,s});while(!q.empty())//堆为空即为所有点都更新{node x=q.top();q.pop();int u=x.now;//记录堆顶(堆内最小的边)并将其弹出if(vis[u]) continue; //没有遍历过才需要遍历vis[u]=1;for(int i=head[u];i;i=e[i].next)//搜索堆顶所有连边{int v=e[i].v;if(dis[v]>dis[u]+e[i].w){dis[v]=dis[u]+e[i].w;pre[v]=u;//松弛操作q.push((node){dis[v],v});//把新遍历到的点加入堆中}}}
}
int main()
{n=read(),m=read(),s=1;for(int i=1,x,y,z;i<=m;i++){x=read(),y=read(),z=1;add(x,y,z);add(y,x,z);}dijkstra();printf("%d ",dis[n]-1);// print(i);// cout<<endl;return 0;
}
J This Ain’t Your Grandpa’s Checkerboard
题意:
一个合法的图满足以下要求:
每行黑块一样多
每列黑块一样多
没有连续的三个黑块
题解:
模拟,照着题意模拟即可
代码:
#include<bits/stdc++.h>
typedef long long ll;
using namespace std;
inline int read(){int s=0,w=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}while(ch>='0'&&ch<='9') s=s*10+ch-'0',ch=getchar();//s=(s<<3)+(s<<1)+(ch^48);return s*w;
}//
const int maxn=40;
char a[maxn][maxn];
int main()
{int n;cin>>n;char ch=getchar();for(int i=1;i<=n;i++){ for(int j=1;j<=n;j++){cin>>a[i][j];}ch=getchar();}bool f=1;int sum=0;int sum1=0;for(int i=1;i<=n;i++){sum1=0;for(int j=1;j<=n;j++){if(a[i][j]==a[i][j-1]&&a[i][j]==a[i][j-2]&&j>=3){f=0;break;}if(i==1){if(a[i][j]=='W')sum++;}else {if(a[i][j]=='W')sum1++;}}if(sum1!=sum&&i!=1){f=0;break;}}if(f==0){cout<<0<<endl;return 0;} sum=0;for(int i=1;i<=n;i++){sum1=0;for(int j=1;j<=n;j++){if(a[j][i]==a[j-1][i]&&a[j][i]==a[j-2][i]&&j>=3){f=0;break;}if(i==1){if(a[j][i]=='W')sum++;}else {if(a[j][i]=='W')sum1++;}}if(sum1!=sum&&i!=1){f=0;break;}}if(f==0){cout<<0<<endl;return 0;} cout<<1<<endl;
}