Codeforces Round #651 (Div. 2) (1370 ABCD题解)

比赛链接
A Maximum GCD
在这里插入图片描述
题意如图,让你在[2,n]中选两个数,使得他们的GCD最大。
思路: 直接输出(n/2).
代码:

#include<bits/stdc++.h>
using namespace std;

typedef long long ll;
int main()
{
    ll t,n;
    cin>>t;
    while(t--)
    {
        cin>>n;
        cout<<(n/2)<<endl;
    }
    return 0;
}

B. GCD Compression
在这里插入图片描述
在这里插入图片描述
题意:给你2*n个数,要求你构造出一个长度(n-1)的序列,这个序列里的每个数都是从哪n个数里面选取两个数取和,每个数只能被选一次,然后要求你构造的那个序列整体的gcd不是1.

思路:直接全部构造2的倍数。
代码:

#include<bits/stdc++.h>
using namespace std;
const int N=1e6+15;
typedef long long ll;
ll a[N],b[N];
int main()
{
    ll t,n,cnt1,cnt2;
    cin>>t;
    while(t--)
    {
        cnt1=0,cnt2=0;
        cin>>n;
        n*=2;
        for(int i=1;i<=n;i++)
        {
            cin>>a[i];
            if(a[i]%2==0)
                a[++cnt1]=i;
            else
                b[++cnt2]=i;
        }
        if(cnt2==0)
            cnt1-=2;
        for(int i=1;i+1<=cnt1;i+=2)
        {
            cout<<a[i]<<" "<<a[i+1]<<endl;
        }
        if(cnt1%2==0)
            cnt2-=2;
       // cout<<cnt1<<" "<<cnt2<<endl;
        for(int i=1;i+1<=cnt2;i+=2)
        {
            cout<<b[i]<<" "<<b[i+1]<<endl;
        }
    }
    return 0;
}

C. Number Game
在这里插入图片描述
博弈游戏,这里有一个整数n,你和imp轮流操作游戏,每次操作只能是下面两种操做之一,看看谁先不能操作谁就输了。
操作1:把n除去他的一个大于一的奇数因子。
操作2:把如果n大于1,可以让n-1.

思路:
首先n=1是必败态,n=2必胜。
然后讨论n大于2的情况
看n是奇数的情况
n是一个大于1的奇数必胜。因为可以直接把n变成1,留给对手必败态。
然后讨论n是偶数的情况。
如果n是2的幂次必输,因为没有奇因子可以除,所以只能减1,留给对面一个大奇数。
然后每一个不是2的幂次的偶数都可以写成 y2^x 的形式,y是一个奇数,x是一个正整数。
令w=2^x。 当w大于2时。 我们必胜,因为我们可以把y除掉,留给对手一个w,w是一个大于2的2的幂次,这是必败态(前面已经证明)。
如果w=2时,y * 2^x 就变成了 y * 2。(y是一个奇数)
如果y是一个质数,我们就必输,因为1操作会留给对面一个2,2操作会留给对面一个奇数,留给对面的都是必胜态。
如果y不是质数,我们必胜,因为我们可以留给对面一个2
一个质数的状态。

代码:


#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
int main()
{
    ll t,n;
    cin>>t;
    while(t--)
    {
        cin>>n;
        if(n==1)
        {
            cout<<"FastestFinger"<<endl;
            continue;
        }
        if(n%2==1||n==2)
        {
            cout<<"Ashishgup"<<endl;
            continue;
        }
        ll cnt=0;
        while(n%2==0)
        {
            cnt++;
            n/=2;
        }
        if(n==1)
        {
            cout<<"FastestFinger"<<endl;
        }
        else
        {
            if(cnt>1)
            {
                cout<<"Ashishgup"<<endl;
            }
            else
            {
                ll f=0;
                for(int i=2;i*i<=n;i++)
                {
                    if(n%i==0)
                        f=1;
                }
                if(f==0)
                    cout<<"FastestFinger"<<endl;
                else
                    cout<<"Ashishgup"<<endl;
            }
        }
    }
    return 0;
}


D. Odd-Even Subsequence
在这里插入图片描述
在这里插入图片描述
给你一个长度为n的初始序列a,让你选k个数构造成序列s。
使得图片上那个表达式的值最小。
思路
首先考虑二分,因为答案具有单调性,如果答案可以,那么比答案大的数也都可以。
考虑check函数。
问题转化:大概可以化为从[ 1 , n ] 中选取任意不相邻的两个数,让他们最大的值最小。这样就很好check了,记录不相邻的比check的值小的个数和k进行判断就好了,check过程中碰到要选的要先看看他前面选了没,如果没有就直接选。check过程分奇偶还要思考一下。
k是偶数情况下,奇序列要在[1,n-1]中取数。偶序列要在[2,n]中取数。

k是奇数情况下:
奇序列要在[1,n]中取(k/2+1个)数。
偶序列要在[2,n-1]中取(k/2)个数。

代码:

#pragma G++ optimize(2)
#include<bits/stdc++.h>
#include<cstdio>
#include<cstring>
#include <iostream>
#include <algorithm>
#include <string>
using namespace std;
typedef  long long ll;//unsigned
typedef unsigned long long ull;
inline bool read(ll &num){char in;bool IsN=false;in=getchar();if(in==EOF) return false;while(in!='-'&&(in<'0'||in>'9')) in=getchar();if(in=='-'){ IsN=true;num=0;}else num=in-'0';while(in=getchar(),in>='0'&&in<='9'){num*=10,num+=in-'0';}if(IsN) num=-num;return true;};
#define rep(i,a,n) for(ll i=a;i<=n;i++)
#define per(i,a,n) for(ll i=a;i>=n;i--)
#define mem(a,b) memset(a,b,sizeof(a))
const ll INF=5e18+7;const ll mod=1e18+7; const ll maxx=1e6+7000;const double eps=1e-9;const double pi=acos(-1);
ll gcd(ll a,ll b){  if(!b) return a;    return gcd(b,a%b);};
ll qpow(ll a,ll b){ll ans=1; 	while(b) 	{		if(b&1) ans=(ans*a)%mod;		a=a*a%mod;		b>>=1;	}	return ans;}
/*  i am hengheng */
// head[maxx];ll deep[maxx];ll vis[maxx];ll dis[maxx];map<ll,ll>mp;
// dx[4]={-1,1,0,0};ll dy[4]={0,0,-1,1};map<ll,ll>mp;/ector<ll>v[maxx];
ll n,m;
ll a[maxx];

ll pipei[maxx];
ll judeg(ll k,ll geshu)
{
	//geshu// xiaoyu  k
	ll cnt=0;
	rep(i,1,n-1)
	{
		if(a[i]<=k&&(pipei[cnt]!=i-1 ||cnt==0))
		{
			pipei[++cnt]=i;
		}
	}
//	prllf("%lld \n",cnt);
    for(ll i=0;i<=cnt+1000;i++)
        pipei[i]=0;
	if(cnt>=geshu) return 1;
	cnt=0;
	rep(i,2,n)
	{
		if(a[i]<=k&&(pipei[cnt]!=i-1 ||cnt==0))
		{
			pipei[++cnt]=i;
		}
	}
//	prllf("%lld \n",cnt);
    for(ll i=0;i<=cnt+1000;i++)
        pipei[i]=0;
	if(cnt>=geshu) return 1;
	return 0;
}
ll judeg2(ll k,ll geshu)
{
	//geshu// xiaoyu  k
	ll cnt=0;
	rep(i,2,n-1)
	{
		if(a[i]<=k&&(pipei[cnt]!=i-1 ||cnt==0))
		{
			pipei[++cnt]=i;
		}
	}
	for(ll i=0;i<=cnt+1000;i++)
        pipei[i]=0;
//	prllf("%lld \n",cnt);
	if(cnt>=geshu) return 1;
	//if(a[1]>k||a[n]>k)
    //    return 0;
    //geshu-=2;
    cnt=0;
    geshu++;
	rep(i,1,n)
	{
		if(a[i]<=k&&(pipei[cnt]!=i-1 ||cnt==0))
		{
			pipei[++cnt]=i;
		}
	}
//	prllf("%lld \n",cnt);
    for(ll i=0;i<=cnt+1000;i++)
        pipei[i]=0;
	if(cnt>=geshu) return 1;
    return 0;
}
int main()
{
	ll k,p,sum,maxl=0,minl=INF;
	ll t;
	cin>>n>>k;
	ll ji=0,ou=0;
	rep(i,1,n) {
		read(a[i]);
		if(i%2==1)
        {
            ji=max(ji,a[i]);
        }
        if(i%2==0)
        {
            ou=max(ou,a[i]);
        }
		minl=min(a[i],minl);
		maxl=max(a[i],maxl);
	}
	if(k==1)
    {
        cout<<minl<<endl;   return 0;
    }
    if(k==n)
    {
        ll op=min(ji,ou);
        cout<<op<<endl;   return 0;
    }
	ll l,r;
	l=minl;r=maxl;
	p=k/2;
	// p
	ll ans1=INF,ans2=INF;
	if(k%2==0)
	{
	    while(l<=r)
        {
            ll mid=(l+r)/2;
            if(judeg(mid,p))
            {
                ans1=min(mid,ans1);
                r=mid-1;
            }
            else l=mid+1;
        }
	}
	else
    {
        while(l<=r)
        {
            ll mid=(l+r)/2;
            if(judeg2(mid,p))
            {
                ans1=min(mid,ans1);
                r=mid-1;
            }
            else l=mid+1;
        }
    }
    ll op=ans1-100;  op=max(op,ll(1));
    if(k%2==0)
    {
        while(1)
        {
            if(judeg(op,p))
            {
                cout<<op<<endl; return 0;
            }
            op++;
        }
    }
    else
    {
        while(1)
        {
            if(judeg2(op,p))
            {
                cout<<op<<endl; return 0;
            }
            op++;
        }
    }
	//cout<<ans1<<endl;
	// ke buxianglin
	return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_43559193/article/details/106881587