不是很全,还是只能做过500+人的题。。
A Game
显然最优策略是永远拿1个。
#include <bits/stdc++.h>
using namespace std;
int main(){
int n1,n2,k1,k2;
cin>>n1>>n2>>k1>>k2;
while(1){
if(n1==0){
printf("Second\n");
break;
}
n1--;
if(n2==0){
printf("First\n");
break;
}
n2--;
}
return 0;
}
B1 Permutations
小数据可以暴力水,用STL自带的函数。
#include <bits/stdc++.h>
using namespace std;
int main(){
int n,m;
cin>>n>>m;
vector<int> v;
for(int i=1;i<=n;i++){
v.push_back(i);
}
for(int i=1;i<m;i++){
next_permutation(v.begin(),v.end());
if(n>2){
for(int j=1;j<n-1;j++){
if(v[j]<v[j-1]&&v[j]<v[j+1]){
i--;
break;
}
}
}
}
for(int i=0;i<n;i++){
printf("%d ",v[i]);
}
return 0;
}
B2 Permutations
这应该算脑洞题了,写一下全排列,发现要使f(p)最大,必须不能出现两个大数夹小数的情况。n+1符合题意的排列,就是在n符合题意的排列的基础上,先把每个数增加1,然后分别在最左边和最右边补上1,也就是说,n每增加1,符合题意的排列数量增加一倍。我们可以得出一个方法,从n开始,往左边或右边递减添数,至于添加在左边还是右边,依据是m的二进制位,详见代码。
#include <bits/stdc++.h>
using namespace std;
int main(){
long long n,m;
cin>>n>>m;
m--;
deque<int> ans;
ans.push_back(n);
int t=n-1;
while(t--){
if(m&1){
ans.push_back(t+1);
}else{
ans.push_front(t+1);
}
m>>=1;
}
for(deque<int>::iterator it=ans.begin();it!=ans.end();it++){
printf("%d ",*it);
}
return 0;
}
C Second price auction
这题知道可以暴力,但是总有细节不知道怎么处理,看了官方题解才A掉。方法是,枚举次高的标,把投标的公司分为三个集合,高于,等于和低于。高于那个集合最多一个公司,等于那个集合至少一个公司,当高于那个集合为空时,等于那个集合至少有两个公司。我们就可以枚举集合的情况,把不合法的集合去掉,合法的那些算出来加上就好了。
#include <bits/stdc++.h>
using namespace std;
int L[6];
int R[6];
double p[6];
double upperThan(int com,int num){
if(num<L[com])return 1;
return max(0,R[com]-num)/p[com];
}
double lowerThan(int com,int num){
if(num>R[com])return 1;
return max(0,num-L[com])/p[com];
}
double equalTo(int com,int num){
if(num<=R[com]&&num>=L[com])return 1/p[com];
return 0;
}
int main(){
int n;
cin>>n;
int MAX=0,MIN=10000;
for(int i=1;i<=n;i++){
cin>>L[i]>>R[i];
MAX=max(MAX,R[i]);
MIN=min(MIN,L[i]);
p[i]=R[i]-L[i]+1.0;
}
int end=pow(3,n);
double ans=0.0;
for(int k=MAX;k>=MIN;k--){
for(int i=1;i<end;i++){
int set[6];
int kind[3]; //大于 等于 小于
kind[0]=kind[1]=kind[2]=0;
int tmp=i;
for(int j=1;j<=n;j++){
set[j]=tmp%3;
tmp/=3;
kind[set[j]]++;
}
if(kind[0]>1)continue;
if(kind[1]==0)continue;
if(kind[0]==0&&kind[1]<2)continue;
double tmp2=k;
for(int j=1;j<=n;j++){
if(set[j]==0){
tmp2*=upperThan(j,k);
}else if(set[j]==1){
tmp2*=equalTo(j,k);
}else{
tmp2*=lowerThan(j,k);
}
}
ans+=tmp2;
}
}
printf("%.10lf\n",ans);
return 0;
}
数据量小,暴力dfs解决。
#include <bits/stdc++.h>
using namespace std;
int b[8];
int n,k;
int fun(){
int re=0;
for(int i=1;i<n;i++){
for(int j=i+1;j<=n;j++){
if(b[i]>b[j])re++;
}
}
return re;
}
int tot;
int rev;
void dfs(int dep){
if(dep<=k){
for(int l=1;l<=n;l++){
for(int r=l;r<=n;r++){
reverse(b+l,b+r+1);
dfs(dep+1);
reverse(b+l,b+r+1);
}
}
}else{
tot++;
rev+=fun();
}
}
int main(){
cin>>n>>k;
for(int i=1;i<=n;i++){
cin>>b[i];
}
dfs(1);
printf("%.10lf",(double)rev/tot);
return 0;
}