原题链接:B:Godsend
大意:
一串数列。A,B 轮流取一些数字。 A 先走,每次从中抽取和为奇数的串,(抽完后自动缩为一个新串)。B 每次从中取和为偶数的串。最后一个无法操作的人输。
思路:
博弈论水题。若和为奇数,那么 A 赢,若和为偶数, A 一开始若能从中抽走奇数,那么 B 输,否则 A 输。
比赛时hack看到的代码写法实在太多了。
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define mem(s,t) memset(s,t,sizeof(s))
//#define D(v) cout<<#v<<" "<<v<<endl
#define inf 0x3f3f3f3f
#define pb push_back
//#define LOCAL
inline void read(int &x){
x=0;char p=getchar();
while(!(p<='9'&&p>='0'))p=getchar();
while(p<='9'&&p>='0')x*=10,x+=p-48,p=getchar();
}
int a[1000];
const int mod=1e9+7;
int main() {
int ans=0,f=0;
int n;
cin>>n;
for(int i=0;i<n;i++){
int x;
cin>>x;
if(x&1) f=1;
ans+=(x%2);
}
if(ans&1) puts("First");
else if(ans%2==0 && f) puts("First");
else puts("Second");
return 0;
}
大意:
题目包装得很多。对于一个数列,
F(n,k)
表示数列中的第 {1,2,3,…n} 个数中选取 k 个数,k 个数中最小数的数学期望。
现在给出两个数列,A,B ,即为上述数列,B 为 k 的集合。
现在求 最大。
看了一下样例是倒序匹配,实际上贪心地想想也是对的。
逆序和大于等于乱序和大于等于顺序和
写法一:
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define mem(s,t) memset(s,t,sizeof(s))
#define D(v) cout<<#v<<" "<<v<<endl
#define inf 0x3f3f3f3f
#define pb push_back
//#define LOCAL
inline void read(int &x){
x=0;char p=getchar();
while(!(p<='9'&&p>='0'))p=getchar();
while(p<='9'&&p>='0')x*=10,x+=p-48,p=getchar();
}
int a[200005],b[200005],c[200005];
int main() {
int m;
read(m);
for(int i=0;i<m;i++) read(a[i]);
for(int i=0;i<m;i++){
read(b[i]);
c[i]=b[i];
}
sort(a,a+m,[&](int x,int y){return x>y;});
sort(b,b+m);
for(int i=0;i<m;i++) printf("%d%c",a[lower_bound(b,b+m,c[i])-b]," \n"[i==m-1]),b[lower_bound(b,b+m,c[i])-b]--;//找到位置,然后这个位置的bi--,防止影响下次查找
return 0;
}
写法二:pair
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define mem(s,t) memset(s,t,sizeof(s))
#define D(v) cout<<#v<<" "<<v<<endl
#define inf 0x3f3f3f3f
#define pb push_back
//#define LOCAL
inline void read(int &x){
x=0;char p=getchar();
while(!(p<='9'&&p>='0'))p=getchar();
while(p<='9'&&p>='0')x*=10,x+=p-48,p=getchar();
}
int a[200005],b[200005],c[200005];
pair<int,int> ans[200005];
int main() {
int m;
read(m);
mem(ans,0);
for(int i=0;i<m;i++) read(a[i]);
for(int i=0;i<m;i++){
read(b[i]);
ans[i]={b[i],i};
}
sort(a,a+m,greater<int>());
sort(ans,ans+m);
for(int i=0;i<m;i++){
int to=ans[i].second;
c[to]=a[i];
}
for(int i=0;i<m;i++) printf("%d%c",c[i]," \n"[i==m-1]);
return 0;
}
顺便复习下pair,二维偏序,排序时先排一维,一维相同时再比较二维。
ps.最近学到了一些c++11的技巧,编译需要编译器支持。