Atcoder Nomura 2020A-C题解

A

Solution

找出该段时间的分钟数 x x x x − k x-k xk即为最终的答案。

Code

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

int a,b,c,d,m;

signed main()
{
	cin>>a>>b>>c>>d>>m;
	cout<<(c*60+d)-(a*60+b)-m<<endl;
	
	return 0;
}

B

Solution

首先,思考一下 p d pd pd的意义。它为总的答案贡献了2(一个 d d d和一个 p d pd pd),而 d d dd dd也为答案贡献了 2 2 2(两个 d d d)。

同时, d d d自己也能为答案产生 1 1 1的贡献,而 p p p自己无法对答案产生任何贡献。

所以我们填 p p p干嘛呢?全填 d d d不就行了?
于是,我们在所有的’?'上填 d d d,再输出即为最终的答案。

Code

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

int n;

signed main()
{
	string s;
	cin>>s;
	n=s.size();
	for (int i=0;i<n;i++)
	{
		if (s[i]=='?')  s[i]='D';
	}
	cout<<s<<endl;
	
	return 0;
}

花絮: 看完题面直接往 d p dp dp方面想(只有 p p p d d d啊)

C

Solution

首先,设 b i b_i bi表示深度为 i i i的那一层中节点的数量

容易得到, b 1 = 1 , b n = a n b_1=1,b_n=a_n b1=1,bn=an。注意最后一层的所有节点均为叶节点

于是,我们从两个角度开始推。

①已知 b 1 = 1 b_1=1 b1=1
容易发现,第 i i i层非叶节点的数量就是 b i − a i b_i-a_i biai;由于这是一棵可爱的二叉树,并且要让答案最大;所以我们要让这 b i − a i b_i-a_i biai个非叶节点的孩子的数量都是2

我知道您觉得单独考虑这东西不行,因为 b n b_n bn不一定是 a n a_n an——于是我们考虑第二种情况。

②已知 b n = A n b_n=A_n bn=An
首先,每个节点有且仅有一个父节点。所以,第 i i i层的节点的数量就是第 i + 1 ( i < n ) i+1(i<n) i+1(in)的节点的数量**加上第 i i i层的叶节点的数量。直接递推。

我知道您很奇怪—— b 1 b_1 b1不一定是1啊~于是,我们决定结合①②考虑答案


现在,我们通过这两种情况,大概得出了 b i b_i bi的值。

容易发现,一层的节点的个数多了是不好的(这是一棵二叉树,如果每一层的节点数量都少那么这种树一定存在);所以, b i b_i bi通过上述两种情况计算出答案分别为 x , y x,y x,y时, b i = m i n ( x , y ) b_i=min(x,y) bi=min(x,y)

注意,当 a i > x i a_i>x_i ai>xi时(不可能在这一层产生这么多的叶节点),应该直接输出 − 1 -1 1

于是答案就是 Σ i = 1 n b i Σ_{i=1}^n b_i Σi=1nbi。时间复杂度 O ( n ) O(n) O(n)


什么?要用高精度?

本蒟蒻解释一下为什么不用高精度。首先,对于任何一棵树,从上到下,每一层节点的数量一定是单调不减的。第 n n n层的节点的数量 ( b n ) (b_n) (bn)一定是每层节点个数中的最大值,所以答案一定小于 b n × n b_n×n bn×n,即 1 0 13 10^{13} 1013。既然最大值就这么一点,那么我们用 l o n g long long l o n g long long存储就可以了。

既然不用高精度,代码就简短啦~

Code

#include <bits/stdc++.h>
#define int unsigned long long
using namespace std;

int n,ans=0;
int a[100005],b[100005],c[100005];

int p[100005][205];

signed main()
{
	cin>>n;
	n++;
	for (int i=1;i<=n;i++)  cin>>a[i];
	
	b[1]=1,c[n]=a[n];
	for (int i=2;i<=n;i++)  b[i]=(b[i-1]-a[i-1])*2;
	for (int i=n-1;i>=1;i--)  c[i]=c[i+1]+a[i];
	for (int i=1;i<=n;i++)  ans+=min(b[i],c[i]);
	for (int i=1;i<=n;i++)
	{
		if (a[i]>b[i])  return cout<<-1<<endl,0;
	}
	cout<<ans<<endl;
	
	return 0;
}

撒花✿✿ヽ(°▽°)ノ✿撒花

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值