Atcoder Beginner Contest 118
Posted jklover
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Atcoder Beginner Contest 118相关的知识,希望对你有一定的参考价值。
A: B +/- A
- 签到题.
B: Foods Loved by Everyone
- 签到题.
C: Monsters Battle Royale
- 怪物的血量一直两两相减,类似于辗转相减法.
- 可以证明,最后存活怪物血量最小值即为所有怪物初始血量的 (gcd) .
D: Match Matching
- 考虑 (dp) 预处理一个数组 (f) , (f[i][j]) 表示第一位用数字 (i) ,后面一共用 (j) 根火柴棒,能拼出数字的最大位数.
- 一共有 (nm) 个状态,每次转移 (O(m)) ,这个 (dp) 的时间复杂度为 (O(nm^2)).
- 得到 (f) 数组后,考虑从高位到低位贪心构造解.
- 每次都选能使后面位数最大的数字作为当前的这一位,若后面位数相同,则选数字大的.
- 最终答案显然不会超过 (n) 位,确定每一位只需比较 (m) 个数字的优劣.这一步时间复杂度为 (O(nm)) .
- 总时间复杂度为 (O(nm^2)) .
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define inf 1e9
inline int read()
{
int x=0;
bool pos=1;
char ch=getchar();
for(;!isdigit(ch);ch=getchar())
if(ch=='-')
pos=0;
for(;isdigit(ch);ch=getchar())
x=x*10+ch-'0';
return pos?x:-x;
}
int x[11]={0,2,5,5,4,5,6,3,7,6};
int a[11],m,N;
const int MAXN=1e4+10;
int f[11][MAXN];
int n;
int dfs(int i,int j)
{
if(f[i][j]!=-1)
return f[i][j];
if(j==0)
return 1;
if(j<0)
return -inf;
f[i][j]=-inf;
for(int k=1;k<=m;++k)
{
if(j>=x[a[k]])
f[i][j]=max(f[i][j],1+dfs(i,j-x[a[k]]));
}
return f[i][j];
}
bool better(int i,int j,int k)
{
if(i-x[a[j]]<0)
return false;
if(!k)
return true;
if(f[a[j]][i-x[a[j]]]>f[a[k]][i-x[a[k]]])
return true;
if(f[a[j]][i-x[a[j]]]==f[a[k]][i-x[a[k]]] && a[j]>a[k])
return true;
return false;
}
int main()
{
n=read(),m=read();
memset(f,-1,sizeof f);
for(int i=1;i<=m;++i)
a[i]=read();
int i,j,k;
for(int i=1;i<=m;++i)
dfs(a[i],n-x[a[i]]);
for(i=n;i;)
{
k=0;
for(j=1;j<=m;++j)
if(better(i,j,k))
k=j;
i-=x[a[k]];
putchar(a[k]+'0');
}
return 0;
}
以上是关于Atcoder Beginner Contest 118的主要内容,如果未能解决你的问题,请参考以下文章
AtCoder Beginner Contest 115 题解