ARC144

ARC 144

比赛情况:一眼订正,鉴定为做起 3 道题。

A - Digit Sum of 2x

2x 进位就不满足 M 最大的条件了,所以 x 不能进位。
然后要求 x 最小,只要 N%40 则最高位为 N%4,否则最高位为 4。后面只能全填 4 了,因为这样位数最小。

点击查看代码
#include <bits/stdc++.h>
using namespace std;
const int MAXN=1e6+50;
int main()
{
	int N;
	cin>>N;
	printf("%d\n",2*N);
	if(N%4!=0)
	printf("%d",N%4);
	for(int i=1;i<=N/4;i++)
	printf("4");
}

B - Gift Tax

贪心地看,要把最小的数弄大的同时把最大的数弄小。
有了贪心策略,就可以二分答案了,对于当前二分的答案,把 A 从小到大排序,双指针判一下就好。

点击查看代码
#include <bits/stdc++.h>
using namespace std;
const int MAXN=1e6+50;
int N;
int a,b;
int A[MAXN],B[MAXN];
bool Check(int Now)
{
	for(int i=1;i<=N;i++)
	{
		B[i]=A[i];
	}
	int l=1,r=N;
	long long Add=0;
	while(l<r)
	{
		if(B[l]>=Now)
		{
			return true;
		}
		else
		{
			Add+=(Now-B[l]-1)/a+1;
			while(Add&&l<r)
			{
				if(B[r]-Now>=Add*b)
				{
					B[r]-=Add*b;
					Add=0;
					break;
				}	
				else
				{
					Add-=(B[r]-Now)/b;
					r--;
				}
			}
		}
		l++;
	}
	if(Add)
	{
		return false;
	}
	else
	{
		return true;
	}
}
int main()
{
	scanf("%d%d%d",&N,&a,&b);
	int l=1e9,r=0;
	for(int i=1;i<=N;i++)
	{
		scanf("%d",&A[i]);
		l=min(l,A[i]);
		r=max(r,A[i]);
	}
	sort(A+1,A+N+1);
	int Mid,ans=0;
	while(l<=r)
	{
		Mid=l+r>>1;
		if(Check(Mid))
		{
			ans=Mid;
			l=Mid+1;
		}
		else
		{
			r=Mid-1;
		}
	}
	cout<<ans;
}

C - K Derangement

考虑无解,只要存在一个值无论在哪里都放不了就无解。也就是 K>N2 时无解。

假设 N 无穷大,那一定是每 2K 一个周期,这个周期内 Ai 的取值为 i+KAi+K 的取值为 i。因为这能够让小的数被第一时间用掉,所以是最优的。

而事实上如果 N 不是 2K 的倍数,就会出问题,最后面会放不下。

所以最后预留一个整的长度为 2K 的段和剩下的长度为 N%2K 的段。

对于这两个段,从后往前填,最大的几个数放在能放的最后一个位置。

剩下没放的位置,和剩下没用过的数字,越前面用越小的数字就行了。

点击查看代码
#include <bits/stdc++.h>
using namespace std;
const int MAXN=1e6+50;
int N,K; 
int Ans[MAXN];
bool Use[MAXN];
priority_queue<int,vector<int>,greater<int> >q;
int main()
{
	scanf("%d%d",&N,&K);
	if(K>N/2)
	{
		puts("-1");
		return 0;
	}
	for(int i=1;i<=N;i++)
	{
		q.push(i);
	}
	int Now=1;
	for(;Now+(K<<1)<=N-(K<<1);Now+=(K<<1))
	{
		for(int i=Now;i<Now+K;i++)
		{
			Ans[i]=i+K;
			Ans[i+K]=i;
			Use[i]=Use[i+K]=true;
		}
	}
	for(int i=Now;i<Now+K;i++)
	{
		Ans[i]=i+K;
		Use[i+K]=true;
	}
	for(int i=N-(K<<1)+1;i<=N-K;i++)
	{
		Ans[i]=i+K;
		Use[i+K]=true;
	}
	for(int i=1;i<=N;i++)
	{
		if(Ans[i]==0)
		{
			while(Use[q.top()])
			q.pop();
			Ans[i]=q.top();
			q.pop();
		}
		printf("%d ",Ans[i]);
	}
}

D - AND OR Equation

抛出一个结论:

fs=f0+is(f2if0)

其中 is 表示 s 二进制表示下第 i 位是 1
按照题解的方法,令 c=f0,gi=f2ic
所以对于任意一组 {c,g0,...,gn1} 都能构造出来一组 f
所以原问题变成求有多少满足条件的上文所说的集合。
根据题意,0cK

咕,明天继续写。

posted @   0htoAi  阅读(194)  评论(2编辑  收藏  举报
点击右上角即可分享
微信分享提示
评论
收藏
关注
推荐
深色
回顶
收起