HDU多校七

总结:
本场题目有些难度,内部配合也不是特别好,爆零确实很难顶,内部再继续查漏补缺!

1009

题意

输入n,x,y三个数,能否构造一个长度为n的全排列,使得最长上升子序列的长度为x,最长下降子序列的长度为y。若能构造,输出YES和这个序列。不能,则输出NO。

思路

可以把n分为若干个长度为y的倒序块,然后判断前面正序的数字是否够x个,如果够则直接输出,否则,把右侧的倒序块一个个转变为正序即可,如果最后一个倒序块被改变,就输出NO。

代码

#include <bits/stdc++.h>
#define IO ios::sync_with_stdio(0), cin.tie(0)
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int maxn = 1e5 + 5;
const int inf = ~0u >> 1;
typedef pair<int, int> P;
#define REP(i, a, n) for (int i = a; i < (n); ++i)
#define PER(i, a, n) for (int i = (n)-1; i >= a; --i)
const ll mod = 1e9 + 7;
int ans[maxn];
int main() {
    IO;
    int t;
    cin >> t;
    while (t--) {
        int n, x, y;
        cin >> n >> x >> y;
        if (x == 1 || y == 1) {
            if (x + y != n + 1) {
                cout << "NO" << endl;
                continue;
            } else {
                 cout<<"YES"<<endl;
                if (x == n) {
                    REP(i, 1, n + 1) {
                        if (i != 1) cout << ' ';
                        cout << i;
                    }
                } else {
                    PER(i, 1, n + 1) {
                        if (i != n) cout << ' ';
                        cout << i;
                    }
                }
                cout << endl;
                continue;
            }
        } else {
            if (x + y - 1 > n) {
                cout << "NO" << endl;
                continue;
            }
            cout<<"YES"<<endl;
            int sum = 0;
            int num = n;
            PER(i, 1, x + 1) {
                int t = min(n - sum - (i - 1), y);
                sum += t;
                int tt = 1;
                //cout << "t = " << t << endl;
                PER(j, num - t + 1, num + 1) { 
                    ans[n - sum + tt] = j; 
                    //cout << "ans[" << n - sum + tt << "] = " << j << endl;
                    tt++;
                }
                

                num -= t;
            }
            REP(i, 1, n + 1) {
                if (i != 1) cout << ' ';
                cout << ans[i];
            }
            cout << endl;
        }
    }
    return 0;

}

1010

题意

注意:不要在一行末尾输出额外的空格。
渡渡鸟正在一个无限的二维平面上慢跑,从(x0,y0)开始。对于一个点(x,y),只有当gcd(x,y)>1时,被认为是好的。
渡渡鸟将在以下策略下在平面上行走无限步:
假设渡渡鸟现在在(x,y),让S成为在(x,y)周围八个点中的好点的集合。Z是S的大小。
他有1/(z+1)的可能性停留在(x,y),有z/(z+1)的可能性移动到一个在S集合内的点上。
如果他选择移动,去往任何在S内的点的可能性是相同的。
定义pi为在行走t步后回到(x0,y0)的可能性,请计算在走无穷多次步数后,pi的大小。

思路

“图上随机游走”算法。建出无向图后,答案就是起点的度数+1,再除以总度数+n。

代码

#include<bits/stdc++.h>
using namespace std;
#define IO ios::sync_with_stdio(false),cin.tie(0);
#define ll long long
#define inf 0x3f3f3f3f
const int N=1e5+5;
//set<string>b;
//set<string>::iterator it;
const int v[8][2]={0,1,0,-1,1,0,-1,0,1,1,-1,-1,-1,1,1,-1};
set<pair<ll,ll>>vis;
void fun(ll x,ll y)
{
	int a1=0,a2=0,i,aa;
	queue<pair<ll,ll>>q;
	q.emplace(x,y);
	vis.emplace(x,y);
	while(q.size())
	{
		tie(x,y)=q.front();
		q.pop();
		if(x==y)
		{
			a1=0,a2=1;
			break;
		}
		a2++;
		for(i=0;i<8;i++)
		{
			ll dx=x+v[i][0];
			ll dy=y+v[i][1];
			if(__gcd(dx,dy)==1)
			{
				continue;
			}
			a2++;
			if(vis.count(make_pair(dx,dy)))
			{
				continue;
			}
			vis.emplace(dx,dy);
			q.emplace(dx,dy); 
		}
		if(!a1) a1=a2;
	}
	aa=__gcd(a1,a2);
	a1/=aa,a2/=aa;
	printf("%d/%d\n",a1,a2);
}
int main()
{
	int T;
	ll x,y;
	cin>>T;
	while(T--)
	{
		scanf("%lld%lld",&x,&y);
		fun(x,y);
	}
    return 0;
}

1007

题意

在一个二维平面内,给出nnn个点。两个玩家在二维平面上玩游戏。
第一个玩家从第一个点开始操作,两个人轮流操作。游戏规则是,当前玩家从当前所在点跳向另外一个点,要求这个点没有被跳过,且本次跳跃的距离要比上一次跳跃的距离要长。特别的,第一次跳跃可以跳任意长度。

思路

我们考虑最长的一条边,如果某个人先手选了这条边两个端点的一个,那么另一个人立刻选另一个,就结束了
然后把所有最长的边去掉后,又变成了一个子问题,还是把剩下的边中最长的选出来,这样递归下去
那么最后如果只剩1一个点没选,那么1无论选其他的哪个点,都是先手选了一个"最大"边的端点,他必输
否则先手必赢

代码


#include<bits/stdc++.h>
using namespace std;
long long x[2005],y[2005];
int vis[2005];
struct Node{
    long long r;
    int u,v;
}d[4000010];
bool cmp(Node a,Node b){
    return a.r>b.r;
}
int main(){
    int t;
    scanf("%d",&t);
    while(t--){
        int n;
        scanf("%d",&n);
        for(int i=0;i<n;i++){
            scanf("%lld%lld",&x[i],&y[i]);
            vis[i]=0;
        }
        int cnt=0;
        for(int i=0;i<n;i++){
            for(int j=0;j<i;j++){
                d[cnt].r=(x[i]-x[j])*(x[i]-x[j])+(y[i]-y[j])*(y[i]y[j]);
              d[cnt].u=i,d[cnt].v=j;
                cnt++;
            }
        }
        sort(d,d+cnt,cmp);
        long long mx=-1;
        int sum=n,flag=0;
        for(int i=0;i<cnt;i++){
            if(vis[d[i].u]||vis[d[i].v])continue;
            set<int>s;
            int j=i;
            while(j<cnt&&d[j].r==d[i].r){
                if(vis[d[j].u]||vis[d[j].v]){j++;continue;}
                s.insert(d[j].u);
                s.insert(d[j].v);
                j++;
            }
            i=j-1;
            for(auto v:s)vis[v]=1;            
            if(vis[0]==1&&sum>1)flag=1;
            sum-=s.size();
        }
        printf(flag?"YES\n":"NO\n");
    }
}


一级目录

题意

思路

代码

©️2020 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页