2020杭电第七场题解Increasing and Decreasing、Game、Jogging

发布于 2020-08-17  0 次阅读


Increasing and Decreasing

思路:

官方题解已经给的很清楚了,直接分块构造就行

在这里插入图片描述

AC Code:

#include<cstdio>
#include<algorithm>
#include<iostream>
using namespace std;
#define endl '\n'
#define INF 0x3f3f3f3f
#define int long long
// #define TDS_ACM_LOCAL
const int N=2e5 +9;
int T,n,x,y,res,tot=0,ans[100005];

void solve(){
    tot=0;
    scanf("%d%d%d",&n,&x,&y);
    if(1ll*x*y<n||n<x+y-1)
    {
        printf("NO\n");
        return ;
    }
    printf("YES\n");
    res=0;
    while(1ll*y*(x-1)>=n-res-1&&res<n)
    {
        res++;
        ans[++tot]=res;
        x--;
    }
    for(int i=res+(n-res)%y;i>res;i--)ans[++tot]=i;
    if((n-res)%y)x--;
    res+=(n-res)%y;
    for(int i=1;i<=x;i++)
    {
        for(int j=res+y;j>res;j--)ans[++tot]=j;
        res+=y;
    }
    for(int i=1;i<n;i++)printf("%d ",ans[i]);
    printf("%d\n",ans[n]);
    return ;
}

signed main(){
	// ios::sync_with_stdio(0);
	// cin.tie(0), cout.tie(0);
#ifdef TDS_ACM_LOCAL
    freopen("D:\\VS code\\.vscode\\testall\\in.txt", "r", stdin);
    freopen("D:\\VS code\\.vscode\\testall\\out.txt", "w", stdout);
#endif
    int T;
    cin>>T;
    while(T--)  solve();
    return 0;
}

Game

思路:

考虑当前的最长距离即可,在最长边中(也可能是多条最长边)如果有人先手选了这条边的两个端点的一个,那么另一个人立刻选另一个即可获胜。
然后就可以转换成子问题,求次最长边,一直往后转换,到无点了即为先手必胜(因为先手可以占据第一个点)
或者最后剩下了一个点如果并且这个元素就是1号点,那么就是先手败(因为其他点对于它来说都是必胜点)

AC Code:

#include<cstdio>
#include<algorithm>
#include<iostream>
#include<vector>
using namespace std;
#define endl '\n'
#define INF 0x3f3f3f3f
#define int long long
// #define TDS_ACM_LOCAL
const int N=2e3 +9;
struct node
{
    int u, v;
    int r;
}dis[N*N];
bool cmp(node a, node b){return a.r<b.r;}

int n, x[N], y[N];
int vis[N];
void solve(){
    cin>>n;
    for(int i=0; i<n; i++)  cin>>x[i]>>y[i], vis[i]=0;
    int cnt=0;
    for(int i=0; i<n; i++){
        for(int j=i+1; j<n; j++){
            dis[cnt].r=(x[i]-x[j])*(x[i]-x[j])+(y[i]-y[j])*(y[i]-y[j]);
            dis[cnt].u=i, dis[cnt++].v=j;
        }
    }
    sort(dis, dis+cnt, cmp);
    int sum=n;
    for(int i=cnt-1; i>=0; i--){
        if(!vis[dis[i].u] && !vis[dis[i].v]){
            sum-=2;
            vis[dis[i].u]=1;
            vis[dis[i].v]=1;
        }
    }       
    if((sum==0) || (sum==1 && vis[0]))     cout<<"YES"<<endl;
    else        cout<<"NO"<<endl;

    return ;
}

signed main(){
	ios::sync_with_stdio(0);
	cin.tie(0), cout.tie(0);
#ifdef TDS_ACM_LOCAL
    freopen("D:\\VS code\\.vscode\\testall\\in.txt", "r", stdin);
    freopen("D:\\VS code\\.vscode\\testall\\out.txt", "w", stdout);
#endif
    int T;
    cin>>T;
    while(T--)  solve();
    return 0;
}

Jogging(图上随机游走)

思路:

官方题解已经说的很明白了

在这里插入图片描述

稍微解释一下,对角线上的点的gcd就是本身(x=y),所以会一直走对角线走下去,所以从起点只要一旦能到对角线上去答案就是0
所以直接bfs求点建图就行

#include<cstdio>
#include<algorithm>
#include<iostream>
#include<queue>
#include<map>
using namespace std;
#define endl '\n'
#define INF 0x3f3f3f3f
#define int long long
// #define TDS_ACM_LOCAL
const int N=2e3 +9;
pair<pair<int,int>,int> a;
int x, y;
int flag, sum, du, du0;
int dir[9][2]={0,0, 0,1, 0,-1, 1,0, 1,1, 1,-1, -1,0, -1,1, -1,-1};  //可行走的方向
map<pair<int,int>, int> mp;
queue<pair<int,int>> q;

inline int gcd(int a,int b){
	return b==0?a:gcd(b,a%b);
}

void bfs(int x, int y){
    queue<pair<int,int>> q;
    q.push({x,y});
    mp.clear();
    mp[{x,y}]=1;
    while (!q.empty())
    {
        pair<int,int> p=q.front(); q.pop();
        int dx, dy;
        for(int i=1; i<=8; i++){
            dx=p.first+dir[i][0];
            dy=p.second+dir[i][1];
            if(dx==dy)  {flag=1; return ;}      //到了对角线上
            if(gcd(dx,dy)>1){
                du++;
                if(!mp[{dx,dy}]){
                    mp[{dx,dy}]=1;
                    q.push({dx,dy});
                    sum++;
                }
            }
        }
        if(p.first==x && p.second==y)   du0=du;     //到了起点,更新起点的度数
    }
    return ;
}

void solve(){
    cin>>x>>y;
    //flag 为判断是否可能到对角线,du为总度数,du0为起点的度数,sum为总的点数(第一个点bfs没记录,所以初始化为1
    flag=du=du0=0; sum=1;
    bfs(x,y);
    if(flag)    {cout<<"0/1"<<endl; return ;}
    int fz=du0+1, fm=du+sum;
    int temp=gcd(fz, fm);
    fz/=temp, fm/=temp;         //答案要求分数为不可约分的形式
    cout<<fz<<"/"<<fm<<endl;
    return ;
}

signed main(){
	ios::sync_with_stdio(0);
	cin.tie(0), cout.tie(0);
#ifdef TDS_ACM_LOCAL
    freopen("D:\\VS code\\.vscode\\testall\\in.txt", "r", stdin);
    freopen("D:\\VS code\\.vscode\\testall\\out.txt", "w", stdout);
#endif
    int T;
    cin>>T;
    while(T--)  solve();
    return 0;
}


平平无奇的在校大学生