牛客网暑期ACM多校训练营(第六场)

  • D. Bulbasaur

题目链接:https://www.nowcoder.com/acm/contest/144/D

题意:一个头能搭配多个身体,一个身体只能搭配一个头,每个搭配都有自己的价值。问如何搭配才能使价值最大。

题解:直接枚举每个身体,找最大的头。。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <vector>
#include <map>
#include <set>
#include <queue>
using namespace std;
 
#define INIT(x) memset(x,0,sizeof(x))
#define eps 1e-8
 
typedef long long ll;
const int inf = 0x3f3f3f3f;
const int maxn = 200005;
 
inline void read(int &x)
{
    int f=1;x=0;char s=getchar();
    while(s<'0'||s>'9'){if(s=='-')f=-1;s=getchar();}
    while(s>='0'&&s<='9'){x=x*10+s-'0';s=getchar();}
    x*=f;
}
 
inline void print(int x)
{
    if(x<0){ putchar('-'); x=-x;}
    if(x>9) print(x/10);
    putchar(x%10+'0');
}
 
ll t,n,m,k;
int a[maxn];
 
int main()
{
    cin>>t;
    int kase = 1;
    while(kase<=t)
    {
        memset(a,0,sizeof(a));
        ll ans = 0;
        scanf("%d%d%d",&n,&m,&k);
        for(int i=0;i<k;i++)
        {
            int x,y,z;
            scanf("%d%d%d",&x,&y,&z);
            a[y] = max(a[y],z);
        }
        for(int i=1;i<=m;i++)
        {
            ans += a[i];
        }
        cout<<"Case #"<<kase<<": "<<ans<<endl;
        kase++;
    }
    return 0;
}

  • A. Singing Contest

题目链接:https://www.nowcoder.com/acm/contest/144/A

题意:总共有2^n个人,要进行n个回合的pk,每个歌手都会准备n首歌,每首歌都有自己的一个“战斗力”,每个歌手都会采取对于自己的最优策略,问那个歌手能赢。

题解:比赛时想的是,如果一名歌手战斗力最大的歌大于它的对手,那么他就能赢。后来发现,应该是找自己歌曲中能战胜对手的战斗力最低的歌曲。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <vector>
#include <map>
#include <set>
#include <queue>
using namespace std;

#define INIT(x) memset(x,0,sizeof(x))
#define eps 1e-8

typedef long long ll;
const int inf = 0x3f3f3f3f;
const int maxn = 20005;

inline void read(int &x)
{
    int f=1;x=0;char s=getchar();
    while(s<'0'||s>'9'){if(s=='-')f=-1;s=getchar();}
    while(s>='0'&&s<='9'){x=x*10+s-'0';s=getchar();}
    x*=f;
}

inline void print(int x)
{
    if(x<0){ putchar('-'); x=-x;}
    if(x>9) print(x/10);
    putchar(x%10+'0');
}

int T,n,a[maxn],ans,m;
vector<int> e[maxn];

void solve(int t)
{
	for(int i=1;i<=m;i+=t*2)
	{
		if(e[i].back()<e[i+t].back())
		{
			int pos = upper_bound(e[i+t].begin(),e[i+t].end(),e[i].back())-e[i+t].begin();
			//cout<<i<<"__"<<pos<<endl;
			e[i].clear();
			e[i+t].erase(e[i+t].begin()+pos);
			e[i].assign(e[i+t].begin(),e[i+t].end());
			if(a[i]==0)
				a[i] = i+t;
			else
				a[i] = a[i+t];
			ans = a[i];
		}
		else {
            int pos = lower_bound(e[i].begin(),e[i].end(),e[i+t].back())-e[i].begin();
			e[i].erase(e[i].begin()+pos);
			if(a[i]==0)
				a[i] = i;
			ans = a[i];
		}
	}
}

int main()
{
	cin>>T;
	int kase = 1;
	while(kase<=T)
	{
		scanf("%d",&n);
		INIT(a);
		ans = 0;
		m = pow(2,n);
		for(int i=1;i<=maxn;i++)
			e[i].clear();
		for(int i=1;i<=m;i++)
		{
			for(int j=0;j<n;j++)
			{
				int x;
				scanf("%d",&x);
				e[i].push_back(x);
			}
			sort(e[i].begin(),e[i].end());
		}
		int t = 1;
		while(t*2<=m)
		{
			solve(t);
			t*=2;
		}
//		cout<<a[3]<<endl;
		cout<<"Case #"<<kase<<": "<<ans<<endl;
		kase++;
	}
	return 0;
}

  • J. Heritage of skywalker

题目链接:https://www.nowcoder.com/acm/contest/144/J

题意:给定a,b,c和一个函数,记ai为这个函数运行第i次的结果,然后求a[1]到a[n]任意两个数的最小公倍数的最大值。

题解:我们知道任意两个数互质的概率为6/π,那么就直接枚举前100大(如果n>100)的数,然后依次求两两之间最小公倍数。

#include <bits/stdc++.h>
using namespace std;

const int inf = 0x3f3f3f3f;
const int maxn = 10000005;
#define eps 1e-8
#define INIT(x) memset(x,0,sizeof(x))
typedef long long ll;

unsigned x,y,z;
unsigned tang(unsigned &x,unsigned &y,unsigned &z)
{
    unsigned t;
    x ^= x << 16;
    x^= x >> 5;
    x ^= x << 1;
    t = x;
    x = y;
    y = z;
    z = t^x^y;
    return z;
}

unsigned gcd(unsigned a,unsigned b)
{
    return b == 0?a:gcd(b,a%b);
}

unsigned long long ans = 0;
int t,n;
unsigned a[maxn];

int main()
{
    cin>>t;
    int kase = 1;
    while(kase<=t)
    {
        scanf("%d%u%u%u",&n,&x,&y,&z);
        INIT(a);
        ans = 0;
        for(int i=1;i<=n;i++)
            a[i] = tang(x,y,z);
        if(n>40)
        {
            nth_element(a,a+40,a+n,greater<unsigned>());
            n = 40;
        }
        for(int i=1;i<=n-1;i++)
            for(int j=i+1;j<=n;j++)
            {
                ans = max(ans,a[i]/gcd(a[i],a[j])*(unsigned long long)a[j]);
            }
        printf("Case #%d: %llu\n",kase,ans);
        kase++;
    }
    return 0;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

总想玩世不恭

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值