洛谷八月月赛II Div.2 A-C题解

PS: D D 有空再补,题目还没看呢QAQ

Solution

A

可以发现答案有单调性,即如果高度为 h h 的房子可以盖出,则高度小于 h h 的房子显然可以盖出。

于是我们果断二分。对于目前的高度 h h ,我们算出 A , B A,B 材料总共缺少的数量,然后再与 c c 一比即可得到二分的值是否可行。

时间复杂度 O ( l o g 2 1 0 9 ) O(log_2{10^9})

B

可以发现,满足要求的序列是两个差为 k k 交互出现的序列,并且长度是偶数。

于是,我们直接枚举交替出现的这两个数中的一个,另一个也可以求出;然后直接求出对于这两个数形成的序列的最大和即可。注意特判 k = 0 k=0 的情况

另外,无合法序列输出的是 N O NO 而不是 1 -1 ,导致本蒟蒻 WA \color{red} \text{WA} 了好多次 QAQ。

C

比较擅长的数学题,奇迹般地 2 2 分钟切掉了

首先,推一推式子。假设这两个数分别是 a m , b m am,bm ,其中 m m 为这两个数的最大公约数;显然 a b a⊥b ( a a b b 互质)且 a , b a,b 均为自然数。

带入,得

x + y + g c d ( x , y ) = l c m ( x , y ) x+y+gcd(x,y)=lcm(x,y)

扫描二维码关注公众号,回复: 11604596 查看本文章

a m + b m + m = a b m am+bm+m=abm

m ( a + b + 1 ) = m a b m(a+b+1)=mab

a + b + 1 = a b a+b+1=ab

a b a b 1 = 0 ab-a-b-1=0

a b a b + 1 = 2 ab-a-b+1=2

( a 1 ) ( b 1 ) = 2 (a-1)(b-1)=2

至此,可以得到 a = 2 , b = 3 a=2,b=3 a = 3 , b = 2 a=3,b=2


但是,我们如何找到形成的序列的最大和呢?

考虑 d p dp 。首先将这个序列按降序排序并去重,用 m a p map 记录下每个数在原序列中出现的次数。

状态设计: d p i dp_i 表示看到第 i i 个数的最大和。

状态转移:

如果第 i i 个数是奇数,那么 1 1 i 1 i-1 的所有数显然不能让它跟在后面,此时 d p i = a i dp_i=a_i

否则,我们考虑让它跟在第 a i 2 × 3 \frac {a_i} 2×3 的后面,即 d p i = d p x + a i dp_i=dp_x+a_i ,其中 x x 为满足 a x = a i 2 × 3 a_x=\frac {a_i} 2×3 的唯一 x x

我们可以用 m a p map 记录下 x x 这个数出现的位置,即可高效进行第二种转移。

时间复杂度 O ( n l o g 2 n ) O(nlog_2n) ,但是由于 S T L STL 的巨大常数导致在洛谷上跑得比蜗牛还慢(当然过了)。

Code

A

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

int a,b,c,now,ans;

bool check(int x)
{
	int need=(x*(x+1))/2,sumv;
	sumv=max(need-a,0ll);
	sumv+=max(need-b,0ll);
	if (sumv<=c)  return true;
	else return false;
}

int Binary_search(int l,int r)
{
	if (l+1==r||l==r)
	{
		if (check(r))  ans=max(ans,r);
		if (check(l))  ans=max(ans,l);
		return ans;
	}
	int mid=(l+r)>>1;
	if (check(mid))  return Binary_search(mid,r);
	else return Binary_search(l,mid);
}

signed main()
{
	cin>>a>>b>>c;
	cout<<Binary_search(0,1e9)<<endl;
	
	return 0;
}

B

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

int n,k,u,v,maxv,cnt,pos;
int a[2000005];

signed main()
{
	cin>>n>>k;
	for (int i=1;i<=n;i++)
	{
		cin>>u>>v;
		a[u]+=v;
		if (u*a[u]>maxv)  maxv=u*a[u],pos=u;
	}
	if (k==0)
	{
		if (a[pos]>=2)  return cout<<maxv<<endl,0;
		else return cout<<"NO"<<endl,0;
	}
	else
	{
		maxv=0;
		for (int i=0;i<=1000000;i++)
		{
			u=a[i],v=a[i+k];
			cnt=min(u,v);
			if (cnt>=2)  maxv=max(maxv,cnt*i+cnt*(i+k));
		}
		if (maxv==0)  cout<<"NO"<<endl;
		else cout<<maxv<<endl;
	}
	return 0;
}

C

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

int n,pos,ans=0;
int a[300005],b[300005],dp[300005];

map<int,int> m;
map<int,int> m2;

bool cmp(int x,int y)
{
	return x>y;
}

signed main()
{
	cin>>n;
	for (int i=1;i<=n;i++)
	{
		cin>>a[i];
		m[a[i]]++;
	}
	sort(a+1,a+n+1,cmp);
	for (int i=1;i<=n;i++)
	{
		if (a[i]!=a[i-1])  b[++pos]=a[i];
	}
	n=pos;
	
	for (int i=1;i<=n;i++)
	{
		if (b[i]&1)  dp[i]=m[b[i]]*b[i],m2[b[i]]+=dp[i];
		else dp[i]=m2[(b[i]/2)*3]+b[i]*m[b[i]],m2[b[i]]+=dp[i];
	}
	for (int i=1;i<=n;i++)  ans=max(ans,dp[i]);
	cout<<ans<<endl;
	
	return 0;
}

猜你喜欢

转载自blog.csdn.net/Cherrt/article/details/108195257
今日推荐