-
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;
}