AtCoder Beginner Contest 091 题解

13 篇文章 0 订阅
13 篇文章 1 订阅

               AtCoder Beginner Contest 091

总结:原本升蓝了要打regular...结果报错名了,只能打不计分的了...

A题AC代码:

#include <bits/stdc++.h>
using namespace std;
int n,m,k;
int main(int argc, char const *argv[])
{
	cin>>n>>m>>k;
	if(n+m<k)cout<<"No"<<endl;
	else cout<<"Yes"<<endl;
	return 0;
}

B题题解:用map记录一下两人分别拥有的水果数,然后跑一个循环找最大差值即可。

AC代码:

#include <bits/stdc++.h>
using namespace std;
map<string,int> Q;
const int maxn = 107;
int n,m,a[maxn],b[maxn];
int main(int argc, char const *argv[])
{
	cin>>n;
	int now = 0;
	for(int i=1;i<=n;i++)
	{
		string s;
		cin>>s;
		if(!Q.count(s))
			{
				Q[s]=now;
				a[now++]=1;
			}
		else a[Q[s]]++;
	}
	cin>>m;
	for(int i=1;i<=m;i++)
	{
		string s;
		cin>>s;
		if(!Q.count(s))
			{
				Q[s]=now;
				b[now++]=1;
			}
		else b[Q[s]]++;
	}
	int ans = 0;
	for(int i=0;i<now;i++)
	{
		ans = max(ans,max(0,a[i]-b[i]));
	}
	cout<<ans<<endl;
	return 0;
}

C题题意:给定2*N个坐标,判断当一个点的X,Y都小于另一个点时可以连接,求前N个点最多可以连接多少后N个点。

C题题解:先判断一个点可以连接的所有点,记录一下,然后跑二分图最大匹配就是答案。

AC代码:

#include <bits/stdc++.h>
using namespace std;
struct node
{
	int x,y;
}a[122],b[122];
int n,g[122][122];
int linker[122];
bool used[122];
bool dfs(int u)
{
    int v;
    for(v=1;v<=n;v++)
        if(g[u][v]&&!used[v])
        {
            used[v]=true;
            if(linker[v]==-1||dfs(linker[v]))
            {
                linker[v]=u;
                return true;
            }    
        }  
    return false;  
}    
int hungary()
{
    int res=0;
    int u;
    memset(linker,-1,sizeof(linker));
    for(u=1;u<=n;u++)
    {
        memset(used,0,sizeof(used));
        if(dfs(u))  res++;
    } 
    return res;   
}     
int main(int argc, char const *argv[])
{
	cin>>n;
	for(int i=1;i<=n;i++)cin>>a[i].x>>a[i].y;
	for(int i=1;i<=n;i++)cin>>b[i].x>>b[i].y;
	for(int i=1;i<=n;i++)
	{
		for(int j=1;j<=n;j++)
		{
			if(a[i].x<=b[j].x&&a[i].y<=b[j].y)g[i][j]=1;
		}
	}
	cout<<hungary()<<endl;
	return 0;
}

D题题意:给定两个个数为N的数组,两两相加得N^2个数,然后求这些数的异或值。

D题题解:HDU5270原题,求异或的题大多按位求值,该题难点在于然后判断两个数相加后的每一位是不是1,对于a+b来说很容易可以看出对于第i位,如果a+b∈[2^i,2^(i+1))∪[3*2^i,2^(i+2))时该位为1.那么应该将a,b对2^(i+1)取模,然后判断,如判断第3位,如果第三位是1,只能有两种结果,分别是0100-0111(不进位)与1100-1111(进位),即[2^i,2^(i+1))∪[3*2^i,2^(i+2)

那么就从最高位开始向下找起,每次找相加大于当前位的数的和,然后取模之后找下一位,因为先找高位,再找低位,所以取模不影响后面的结果。

AC代码:

#include <iostream>
#include <algorithm>
using namespace std;

typedef unsigned long long ll;
const int maxn=(int)2e5+5;
int n;
ll a[maxn],b[maxn],c[maxn];

void merge (ll *p,ll mod) {   //在给定的mod下归并排序
	int i,j,k,m;
	for(i=1;i<=n;i++) {
		c[i]=p[i];
		if(p[i]>=mod)c[i]=p[i]%mod;
	}
	c[n+1]=mod<<1;
	sort(c+1,c+1+n);
	for(int i=1;i<=n;i++)p[i]=c[i];
}

ll bigthan (ll m) {             //大于m的数对对数
	int i,j=n;ll ans=0;
	for (i=1;i<=n;i++) {
		while ((a[i]+b[j])>=m&&j>0) j--;
		ans+=n-j;
	}
	return ans;
}

bool get (ll mod) {               //考虑mod位是否为1
	merge (a,mod<<1);
	merge (b,mod<<1);
	ll ans = bigthan(mod) + bigthan(3*mod) - bigthan(mod<<1);
	if ( ans%2 ) return true;
	return false;
}

int main () 
{
	int i;
	ll mod,ans;
	cin>>n;
	for(i=1;i<=n;i++) cin>>a[i];
	for(i=1;i<=n;i++) cin>>b[i];
	sort(a+1,a+n+1);sort(b+1,b+n+1);
	ans=0;mod=(ll)1<<28;
	while(mod) {
		if (get(mod)) 
			ans+=mod;
		mod=mod>>1;
	}
	cout<<ans<<endl;
}


评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值