首页 > 其他分享 >ARC166B题解

ARC166B题解

时间:2023-10-19 11:02:29浏览次数:48  
标签:geq return BC int 题解 ll num ARC166B

发现还没有和我一样的做法。

觉得 B 比 A 好想的多。

令 \(A_i\) 为 \(a_i\) 变成 \(A\) 的倍数最少次数,\(B_i,C_i,AB_i,AC_i,BC_i,ABC_i\) 同理。

那么我们就有 \(A_i=(A-A\bmod {a_i})\bmod A\),其他同理。

这一大坨东西显然都能在 \(O(n)\) 的时间复杂度内算出来。

剩下的就很好写了。

先把所有的东西排个序。

如果 \(n\geq 3\),那么可以用 \(A_i,B_i,C_i\) 的每一个的前三个来计算答案。

如果 \(n\geq 2\),那么可以用 \(AB_i,AC_i,BC_i\) 的每一个的前两个来计算答案。

如果 \(n\geq 3\),那么可以用 \(ABC_i\) 来计算答案。

最后取个 \(\min\) 就好了。

记得判断取的数是不是同一个数。

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

#define ll long long
#define db double

const int mod=998244353;
const int N=2e5+10;
const ll inf=1e18;

int T;
int n,m,q;
ll a,b,c;
ll ab,ac,bc,abc;
ll p;

ll gcd(ll x,ll y)
{
	if(!y) return x;
	return gcd(y,x%y);
}
ll lcm(ll x,ll y)
{
	return x*y/gcd(x,y);
}

struct num
{
	ll num;
	int id;
}A[N],B[N],C[N],AB[N],AC[N],BC[N],ABC[N];

bool cmp(num x,num y)
{
	return x.num<y.num;
}

ll ans=inf;

int main()
{
	scanf("%d%lld%lld%lld",&n,&a,&b,&c);
	ab=lcm(a,b);
	bc=lcm(b,c);
	ac=lcm(a,c);
	abc=lcm(a,lcm(b,c));
	for(int i=1;i<=n;i++)
	{
		scanf("%lld",&p);
        
		//这一部分当时赛时 sb 了写得比较复杂,可以直接用上文的式子来计算。
		A[i]=num{p%a?a-p%a:0,i};
		B[i]=num{p%b?b-p%b:0,i};
		C[i]=num{p%c?c-p%c:0,i};
		
		AB[i]=num{p%ab?ab-p%ab:0,i};
		AC[i]=num{p%ac?ac-p%ac:0,i};
		BC[i]=num{p%bc?bc-p%bc:0,i};
		
		ABC[i]=num{p%abc?abc-p%abc:0,i};
	}
	sort(A+1,A+1+n,cmp);
	sort(B+1,B+1+n,cmp);
	sort(C+1,C+1+n,cmp);
	sort(AB+1,AB+1+n,cmp);
	sort(AC+1,AC+1+n,cmp);
	sort(BC+1,BC+1+n,cmp);
	sort(ABC+1,ABC+1+n,cmp);
	if(n>=3)
	{
		for(int i=1;i<=3;i++)
			for(int j=1;j<=3;j++)
				for(int k=1;k<=3;k++)
				{
					if(A[i].id!=B[j].id&&B[j].id!=C[k].id&&A[i].id!=C[k].id) ans=min(ans,A[i].num+B[j].num+C[k].num);
				}
	}
	if(n>=2)
	{
		for(int i=1;i<=2;i++)
			for(int j=1;j<=2;j++)
			{
				if(AB[i].id!=C[j].id) ans=min(ans,AB[i].num+C[j].num);
			}
		for(int i=1;i<=2;i++)
			for(int j=1;j<=2;j++)
			{
				if(AC[i].id!=B[j].id) ans=min(ans,AC[i].num+B[j].num);
			}
		for(int i=1;i<=2;i++)
			for(int j=1;j<=2;j++)
			{
				if(BC[i].id!=A[j].id) ans=min(ans,BC[i].num+A[j].num);
			}
	}
	ans=min(ans,ABC[1].num);
	printf("%lld",ans);
	return 0;
}

标签:geq,return,BC,int,题解,ll,num,ARC166B
From: https://www.cnblogs.com/osfly/p/17774229.html

相关文章

  • [题解]CF1881G Anya and the Mysterious String
    思路发现如果一个字符串中有长度大于等于\(2\)回文子串,必定有长度为\(2\)的回文子串或长度为\(3\)的回文子串,并且形如:aa和aba。所以考虑用线段树这两种情况。维护一段区间的最左、次左、最右、次右的元素,同时用两个标记变量\(f_1,f_2\)分别表示这个区间中是否出现形如......
  • [AGC020F] Arcs on a Circle 题解
    ArcsonaCircle首先,一个非常自然的想法是尝试断环成链。怎么断呢?我们发现,选择最长线段的起点处截断是个非常好的选择,因为不可能有一个线段完全覆盖它。这之后,一个紧接着的想法就是DP。假如把描述中的全部“实点”改成“整点”的话,那么这题是比较trivial的,可以通过随便状压......
  • 洛谷 P4749 [CERC2017] Kitchen Knobs 题解
    KitchenKnobs首先,一个trivial的想法是,因为每个旋钮如果上面的数字并非全部相同则其必有唯一最优位置,故直接扔掉那些全部相同的旋钮,对于剩余的求出其最优位置。明显此位置是一\(0\sim6\)的数。因为是区间同时旋转,所以转成数之后就是区间加同一个数。一个经典套路是差分。这......
  • [ABC207F] Tree Patrolling 题解
    [ABC207F]TreePatrolling弱智DP题,设\(f(i,j,0/1/2)\)表示在点\(i\),子树中有\(j\)个点被覆盖,且\(i\)点自身状态是未被覆盖/被自身覆盖/被某个儿子覆盖,然后树上背包更新就行了。代码:#include<bits/stdc++.h>usingnamespacestd;#defineintlonglongconstintmo......
  • CF1542E2 Abnormal Permutation Pairs (hard version) 题解
    AbnormalPermutationPairs(hardversion)两个限制:字典序小、逆序对大,一个显然的想法就是确保一对关系,统计另一对关系。确保哪一对呢?我们想了想,决定确保字典序小,因为字典序是可以贪心的。具体而言,我们考虑两个排列自第\(i\)位开始出现了不同。这样子,我们便将两个排列各自划......
  • AT_tdpc_tree 木 题解
    木弱智DP题,直接设\(f_i\)表示\(i\)子树内染色的方案数,然后每次合并一个点与它的儿子即可(具体而言,因为儿子间独立,所以方案数就是二项式系数)。需要注意的是因为第一条边可以在任意位置,所以要以每个点为根各DP一次。但是这样每条边会被算两次,所以乘以2的逆元即可。时间......
  • [ARC072E] Alice in linear land 题解
    [ARC072E]Aliceinlinearland首先,一个trivial的想法是记\(f_i\)表示第\(i\)步前离终点的距离,于是\(f_i=\min\Big(f_{j-1},|f_{j-1}-d_i|\Big)\)。然后,我们设\(f_i'\)表示在修改第\(i\)步后,此时离终点的距离。明显,\(f_i'\)可以为任意不大于\(f_i\)的值,因为此时......
  • CF568E Longest Increasing Subsequence 题解
    LongestIncreasingSubsequenceLIS问题有两种主流\(O(n\logn)\)解法,最常见的树状数组法,以及不那么常见的二分法。然后考虑本题,发现一个神奇的思路就是求出LIS后倒序复原出数组。进一步思考后发现,因为本题是LIS(LongestIncreasingSubsequence)而非LNDS(LongestNon-Decr......
  • [AGC046D] Secret Passage 题解
    SecretPassage稍微观察一下就能发现,任一时刻,我们剩下的东西必然是一段定死了的后缀,加上一些可以任意塞位置的0与1。考虑任意一个由上述时刻生成的串,就会发现它与该后缀的最长公共子序列长度即为后缀长度,且还剩余一些0与1。于是考虑模拟最长公共子序列的过程。设\(g_{i,j......
  • Atcoder Beginner Contest 324 G Generate Arrays 题解-Treap
    为了更好的阅读体验,请点击这里题目链接套上平衡树板子就能做的很快的题,然后因为是指针存树,因此交换只需要把序列大小较小的挨个拿出来插到相应的地方即可。复杂度\(O(N\log^2N)\)。但是一定要记住不可以直接使用std::swap交换包含带有指针的类的实例(如代码中的Treap类)!......