题解-ARC126

https://atcoder.jp/contests/arc126

A - Make 10

总共有 ([2,2,3,3],[3,3,4],[2,4,4],[2,2,2,4],[2,2,2,2,2]) 五种拼法,显然如果按照一种拼法拼了就会一直接着按这种拼法,所以我们给这5种拼法一个优先级,按顺序依次执行即可。

#include<bits/stdc++.h>
typedef long long ll;
ll zsy[3],d[5][3]={{2,2,0},{0,2,1},{1,0,2},{3,0,1},{5,0,0}};
int p[5];
int main(){
	int T;
	scanf("%d",&T);
	while(T--){
		ll a,b,c,ans=0;
		scanf("%lld%lld%lld",&a,&b,&c);
		for(int i=0;i<5;i++)p[i]=i;
		do{
			ll nowans=0;
			zsy[0]=a,zsy[1]=b,zsy[2]=c;
			for(int i=0;i<5;i++){
				int x=p[i];
				ll now=1e15;
				for(int j=0;j<3;j++)
					if(d[x][j]!=0)now=std::min(now,zsy[j]/d[x][j]);
				for(int j=0;j<3;j++)
					zsy[j]-=now*d[x][j];
				nowans+=now;
			}
			ans=std::max(ans,nowans);
		}while(std::next_permutation(p,p+5));
		printf("%lld
",ans);
	}
	return 0;
}

B - Cross-free Matching

注意到最后取法按 a 排序后不存在逆序对,所以我们不妨直接按 a 排序求 lis,要求相同的 a 不能取到,于是相同的 a 的 b 从大到小排即可。

#include<bits/stdc++.h>
typedef long long ll;
struct node{
	int a,b;
	friend bool operator<(node x,node y){return x.a==y.a?x.b>y.b:x.a<y.a;}
}p[200005];
int n,m;
int c[200005],f[200005],ans;
void add(int x,int v){
	while(x<=n){
		c[x]=std::max(c[x],v);
		x+=x&-x; 
	}
}
int ask(int x){
	int ret=0;
	while(x){
		ret=std::max(ret,c[x]);
		x-=x&-x;
	}
	return ret;
}
int main(){
	n=read();m=read();
	for(int i=1;i<=m;i++)
		p[i].a=read(),p[i].b=read();
	std::sort(p+1,p+1+m);
	for(int i=1;i<=m;i++)
		f[i]=std::max(1,ask(p[i].b-1)+1),add(p[i].b,f[i]),ans=std::max(ans,f[i]);
	printf("%d
",ans);
	return 0;
}

C - Maximize GCD

对于一个极大 d 满足所有数都是他的倍数那么他就是 gcd。考虑枚举gcd=d计算需要几步,其实就是 ((d-a_imod d)mod d),一开始我以为有单调性于是就写了个二分,但其实这显然没有单调性。但也只是在 (max A) 以内没有,于是我们考虑对小于 (max A) 的数特殊处理,显然可以枚举倍数计算 (a_imod d),于是就 (max A ln max A) 了。

#include<bits/stdc++.h>
typedef long long ll;
int N;
ll zsy[600005],K,ans,s1[600005],s2[600005];
bool check(ll d){
	ll ret=0;
	for(int i=1;i<=N;i++){
		ret+=(d-zsy[i]%d)%d;
		if(ret>K)return 0;
	}
	return 1;
}
int main(){
	scanf("%d%lld",&N,&K);
	for(int i=1;i<=N;i++)scanf("%lld",zsy+i),s1[zsy[i]]+=zsy[i],s2[zsy[i]]+=1;
	std::sort(zsy+1,zsy+1+N);
	for(int i=1;i<=600000;i++)s1[i]+=s1[i-1],s2[i]+=s2[i-1];
	for(int i=1;i<=300000;i++){
		ll now=0;
		for(int j=0;j<=300000;j+=i){
			// [j+1,j+i-1] 
			now+=(s2[j+i-1]-s2[j])*(j+i)-(s1[j+i-1]-s1[j]);
			if(now>K)break;
		}
		if(now<=K){
			ans=i;
		}
	}
	ll l=zsy[N]+1,r=2e18;
	while(l<=r){
		ll mid=(l+r)>>1;
		if(check(mid)){
			ans=std::max(ans,mid);
			l=mid+1;
		}else{
			r=mid-1;
		}
	}
	printf("%lld
",ans);
	return 0;
}
原文地址:https://www.cnblogs.com/zcr-blog/p/15314241.html