比赛链接
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;
}