eg:Round 615我是开小号打的,一场上蓝真滴很高兴QvQ,E题着实脑子抽了没来得及写完,贪心写的很fake。赛后第二天补了E,然后今天才补了F。那开始补档。
A. Collecting Coins
题意:T组数据,每组给出四个整数A,B,C,N。问是否可以合理分配N使得A+a=B+b=C+c且a+b+c=N。
题解:将三个整数从小到大排序,假设排完的顺序为A,B,C。先看N是否大于等于C-A+C-B,再看N是否是3的倍数就好了。
#include "stdio.h"
#include "string.h"
#include "iostream"
#include "algorithm"
#include "vector"
#include "math.h"
#include "map"
#include "set"
using namespace std;
const int maxn=1e5+10;
const int INF=0x3f3f3f;
const int mod=1e9+7;
int f[5];
int main(){
int T;
scanf("%d",&T);
while(T--){
int a,b,c,n;
scanf("%d%d%d%d",&f[1],&f[2],&f[3],&n);
sort(f+1,f+1+3);
int ans=f[3]-f[1]+f[3]-f[2];
if(ans>n)puts("NO");
else{
ans=n-ans;
if(ans%3==0)puts("YES");
else puts("NO");
}
}
return 0;
}
B. Collecting Packages
题意:T组数据,每组有n个点。出发点在(0,0),每次只能向上或者向右走,问是否可以完全走完这n个点,如果可以走完按照字典序最小输出。
题解:sort排序题,显然R<U,所以我们先排横座标再排纵座标,然后扫描一遍即可。
#include "stdio.h"
#include "string.h"
#include "iostream"
#include "algorithm"
#include "vector"
#include "math.h"
#include "map"
#include "set"
using namespace std;
const int maxn=1e5+10;
const int INF=0x3f3f3f;
const int mod=1e9+7;
int n;
struct arr{
int x,y;
}f[1010];
int m[1010][1010];
bool cmp(arr a,arr b){
if(a.x==b.x)return a.y<b.y;
return a.x<b.x;
}
string s;
int main(){
int T;
scanf("%d",&T);
while(T--){
s.clear();
scanf("%d",&n);
for(int i=1;i<=n;i++)scanf("%d%d",&f[i].x,&f[i].y);
sort(f+1,f+1+n,cmp);
int nowx=0,nowy=0,flag=0,cnt=0;
for(int i=1;i<=n;i++){
if(f[i].x>=nowx && f[i].y>=nowy){
for(int j=0;j<f[i].x-nowx;j++)s=s+"R";
for(int j=0;j<f[i].y-nowy;j++)s=s+"U";
nowx=f[i].x;nowy=f[i].y;
}else {
flag=1;
break;
}
}
if(flag)puts("NO");
else{
puts("YES");
cout<<s<<endl;
}
}
return 0;
}
C. Product of Three Numbers
题意:t组数据,给出一个十进制正整数n,问可否找出三个整数a,b,c使得,且
题解:直接对n的所有因数进行暴力枚举,再对其中一个因数进行暴力枚举,检查三个数是否相等即可。
#include "stdio.h"
#include "string.h"
#include "iostream"
#include "algorithm"
#include "vector"
#include "math.h"
#include "map"
#include "set"
using namespace std;
const int maxn=1e5+10;
const int INF=0x3f3f3f;
const int mod=1e9+7;
int n;
int f[4];
int main(){
int T;
scanf("%d",&T);
while(T--){
scanf("%d",&n);
int flag=0;
for(int i=2;i*i<=n;i++)
if(n%i==0){
for(int j=2;j*j<=n/i;j++)
if(j!=i && (n/i)%j==0){
if(n/i/j!=i && n/i/j!=j){
f[0]=i,f[1]=j,f[2]=n/i/j;
flag=1;
break;
}
if(flag)break;
}
if(flag)break;
}
if(!flag)puts("NO");
else {
sort(f,f+3);
puts("YES");
printf("%d %d %d\n",f[0],f[1],f[2]);
}
}
return 0;
}
D. MEX maximizing
题意:给出q个整数和一个整数x,每次读入一个整数n,可以将n变成或者,其中d为任意正整数,此外进行MEX操作,输出最大的MEX值。(MEX:输出最小的不在集合里的非负整数)
题解:每次读入一个数字,都取模x,按照最小的往上累加即可。用map记录一下,答案每次往上check即可。
#include "stdio.h"
#include "string.h"
#include "iostream"
#include "algorithm"
#include "vector"
#include "math.h"
#include "map"
#include "set"
using namespace std;
const int maxn=4e5+10;
const int INF=0x3f3f3f;
const int mod=1e9+7;
int n,q,x;
map<int,int>mmap;
int f[maxn];
int main(){
scanf("%d%d",&q,&x);
int ans=0;
while(q--){
int s;
scanf("%d",&s);
s%=x;
if(mmap[s]==1)mmap[f[s]+x]=1,f[s]+=x;
else mmap[s]=1,f[s]=s;
while(mmap[ans]==1)ans++;
//for(int i=0;i<10;i++)printf("%d ",mmap[i]);
printf("%d\n",ans);
}
return 0;
}
E. Obtain a Permutation
题意:给出一个nm的矩阵,每次可以从两个操作里面选择一个(1:任意替换a[i][j]为1~nm的数中的任意一个,2:任意转动第i列),问将矩阵排列成1 2 3 …… n*m的矩阵要最少多少次。
题解:对每一列考虑贪心。f[i]表示向上移动i次则可以将该列达到最终状态且需要改变f[i]个该列的元素。将f数组全置为n,判断该元素是否属于该列,如果属于,则判断对应向上移动几次,假设移动p次,则,之后只要扫描一遍数组选个最小的即可。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=2e5+10;
const int mod=1e9+7;
const int INF=0x3f3f3f3f;
ll read(){
ll f=1,x=0;char ch;
do{ch=getchar();if(ch=='-')f=-1;}while(ch<'0'||ch>'9');
do{x=x*10+ch-'0';ch=getchar();}while(ch>='0'&&ch<='9');
return f*x;
}
vector<int>G[maxn];
int f[maxn];
int n,m;
ll ans;
int main(){
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)G[i].push_back(0);
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++){
int x;
scanf("%d",&x);
G[i].push_back(x);
}
for(int i=1;i<=m;i++){
for(int j=1;j<=n;j++)f[j]=n;
for(int j=1;j<=n;j++)
if((G[j][i]-i)%m==0){
int k=(G[j][i]-i)/m+1;
if(k>n)continue;
if(j<k)j+=n;
f[j-k+1]--;
if(j>n)j-=n;
}
int sum=INF;
for(int j=1;j<=n;j++)sum=min(sum,f[j]+j-1);
ans+=1ll*sum;
}
printf("%lld\n",ans);
return 0;
}
F. Three Paths on a Tree
题意:任给一颗树,找出树上三个点a,b,c使得这三个点之间的简单路径最长。
题解:贪心的思想,找出树的直径,就可以确定a点和b点了。之后枚举其余的点到a和b距离找到一个最长的即可。
#include "stdio.h"
#include "string.h"
#include "iostream"
#include "algorithm"
#include "vector"
#include "math.h"
#include "map"
#include "set"
#include "queue"
using namespace std;
typedef long long ll;
const int maxn=2e5+10;
const int INF=0x3f3f3f;
const int mod=1e9+7;
vector<int>G[maxn];
queue<int>q;
int n,a,b,c,pos,st,sum;
int vis[maxn],dis[maxn],dis1[maxn],dis2[maxn];
int ans1,ans2,ans3;
void bfs(int x){
q.push(x);
memset(vis,0,sizeof(vis));
memset(dis,0,sizeof(dis));
vis[x]=1;
int u=x,cnt=0;
while(!q.empty()){
int v=q.front();
q.pop();
for(int i=0;i<G[v].size();i++)
if(!vis[G[v][i]]){
vis[G[v][i]]=1;
q.push(G[v][i]);
dis[G[v][i]]=dis[v]+1;
if(dis[G[v][i]]>cnt)u=G[v][i],cnt=dis[G[v][i]];
}
}
pos=u;
}
int main(){
scanf("%d",&n);
for(int i=1;i<n;i++){
int x,y;
scanf("%d%d",&x,&y);st=x;
G[x].push_back(y);
G[y].push_back(x);
}
bfs(st);a=pos;//find a
bfs(a);b=pos;//find b
for(int i=1;i<=n;i++){//other to a_dis
dis1[i]=dis[i];
if(dis1[i]>sum){
b=i;sum=dis1[i];ans1=dis1[i];
}
}
bfs(b);sum=0;
for(int i=1;i<=n;i++){//other to b_dis
dis2[i]=dis[i];
if(dis1[i]>sum)sum=dis2[i];
}
for(int i=1;i<=n;i++)//find c
if(dis1[i]+dis2[i]>ans2+ans3 && i!=a && i!=b){
c=i;
ans2=dis1[i],ans3=dis2[i];
}
printf("%d\n",(ans1+ans2+ans3)/2);
printf("%d %d %d\n",a,b,c);
return 0;
}