第八届“图灵杯”NEUQ-ACM程序设计竞赛个人赛 补题-(Seek the Joker II、建立火车站)
第八届“图灵杯”NEUQ-ACM程序设计竞赛个人赛
传送
Seek the Joker II
威佐夫博弈(Wythoff's game):
有两堆各若干个物品,两个人轮流从任一堆取至少一个或同时从两堆中取同样多的物品,规定每次至少取一个,多者不限,最后取光者得胜。
分析
这种情况下是颇为复杂的。
我们用(a[k],b[k])(a[k] ≤ b[k] ,k=0,1,2,...,n)表示两堆物品的数量并称其为局势,如果甲面对(0,0),那么甲已经输了,这种局势我们称为奇异局势。
前几个奇异局势是:(0,0)、(1,2)、(3,5)、(4,7)、(6,10)、(8,13)、(9,15)、(11,18)、(12,20)。(注:k表示奇异局势的序号, 第一个奇异局势k=0)
可以看出,a[0]=b[0]=0,a[k]是未在前面出现过的最小自然数,而 b[k]= a[k] + k。
结论
a[k]=(b[k]-a[k])*k;
k=0.618 (黄金分割率)
常用 double k=(sqrt(5.0)+1)/2来做精确值。
题解
所以只需判断k*(b[k]-a[k])是否等于a[k]即可
Code
#include<bits/stdc++.h>
#define IO ios::sync_with_stdio(false);cin.tie(0);cout.tie(0)
using namespace std;
const int inf=0x3f3f3f3f;
typedef long long ll;
const int N=100007;
const ll mod=998244353;
int main(){
IO;
int t=1;
cin>>t;
while(t--){
ll n,x;
cin>>n>>x;
ll a=n-x,b=x-1;
if(a>b)swap(a,b);
double m=(sqrt(5.0)+1.0)/2.0;
ll y=(b-a)*m;
if(y!=a)cout<<"yo xi no forever!"<<endl;
else cout<<"ma la se mi no.1!"<<endl;
}
return 0;
}
建立火车站
思路
求出建立站台后的相邻两站台距离的最大值,并且使其尽可能小。
二分找出答案,边界值为第一个站台和最后一个站台之间的距离。
比赛时没想到二分
Code
#include<bits/stdc++.h>
#define IO ios::sync_with_stdio(false);cin.tie(0);cout.tie(0)
using namespace std;
const int inf=0x3f3f3f3f;
typedef long long ll;
const int N=100007;
const ll mod=998244353;
ll a[N];
int n;
ll k;
bool check(ll x){
ll p=k;
for (int i = 1; i < n; ++i)
{
if(a[i]-a[i-1]>x){
p-=(a[i]-a[i-1])/x-((a[i]-a[i-1])%x==0);
}
}if(p<0)return false;
else return true;
}
int main(){
IO;
int t=1;
//cin>>t;
while(t--){
cin>>n>>k;
for (int i = 0; i < n; ++i)
{
cin>>a[i];
}sort(a,a+n);
ll l=0,r=a[n-1]-a[0];
while(l<r){
ll mid=(l+r)>>1;
if(check(mid))
r=mid;
else
l=mid+1;
}cout<<l<<endl;
}
return 0;
}
Code will change the world !

浙公网安备 33010602011771号