首页 > 其他分享 >LibreOJ526. 「LibreOJ β Round #4」子集

LibreOJ526. 「LibreOJ β Round #4」子集

时间:2023-04-07 13:13:27浏览次数:49  
标签:head gcd LibreOJ int LibreOJ526 ec leq 子集 Round

简要题意

给出一个长度为 \(n\) 的序列 \(a\)。你需要选出它的一个子集 \(S\)。使其满足对于任意两个元素 \(i,j\)。满足:

\[\gcd(i,j)\cdot\gcd(i+1,j+1)\neq1 \]

输出满足条件的子集大小的最大值。

\(1 \leq n \leq 500,1 \leq a_i \leq 10^{18}\)

思路

这道题比 Codeforces Gym 104059B - Breeding Bugs 更为简单。

首先对于选出一个子集两两满足特定约束的问题,有一个经典思路就是将满足条件转换为不满足条件,然后对于不满足条件的两个点连一条边,答案就是最大独立集。

但是一般图最大独立集是 NPC 问题。考虑发掘这张图的特殊性质。

引理:若 \(i\equiv j\pmod{2}\),则 \(\gcd(i,j)\cdot\gcd(i+1,j+1)\neq1\)。(但是这个命题的逆命题不成立)。

Proof:若 \(i\equiv j\pmod{2}\),则 \(\gcd(i,j)\equiv0\pmod{2}\),所以上式必定不为 \(1\)。得证。

于是我们可以按照奇偶性黑白染色,就可以把原图变成二分图了。

然后用匈牙利即可。

代码

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

const int N = 505;
int n;

struct edge{
	int nxt,to;
} g[N*N];
int head[N],ec,a[N],mch[N],vist[N];

void add(int u,int v){
	g[++ec].nxt=head[u];
	g[ec].to=v;head[u]=ec;
}

bool dfs(int u,int tag){
	if(vist[u]==tag) return 0;
	vist[u]=tag;
	for(int i=head[u];i;i=g[i].nxt){
		int v=g[i].to;
		if(!mch[v] || dfs(mch[v],tag)){
			mch[v]=u;
			return 1;
		}
	}
	return 0;
}

signed main(){
	ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
	cin>>n;
	for(int i=1;i<=n;i++) cin>>a[i];
	for(int i=1;i<=n;i++){
		if(!(a[i]&1)) continue;
		for(int j=1;j<=n;j++){
			if(a[j]&1) continue;
			if(gcd(a[i],a[j])*gcd(a[i]+1,a[j]+1)==1){
				add(i,j);
			}
		}
	}
	int ans=n;
	for(int i=1;i<=n;i++){
		if(dfs(i,i)) ans--;
	}
	cout<<ans;
	return 0;
} 

标签:head,gcd,LibreOJ,int,LibreOJ526,ec,leq,子集,Round
From: https://www.cnblogs.com/zheyuanxie/p/loj526.html

相关文章

  • Cesium案例(五) Underground Color
       Cesium.Ion.defaultAccessToken=    token   constviewer=newCesium.Viewer("cesiumContainer");   constscene=viewer.scene;   constglobe=scene.globe;   //获取或设置深度测试椭球。   scene.screenSpaceCa......
  • CodeTON Round 4 (Div. 1 + Div. 2, Rated, Prizes!)(持续更新)
    Preface唉难得熬夜打一把还天天掉分,苦路西这把状态奇差,CD两个傻逼题都写的很慢,然后做E的时间太少最后又是经典比赛结束才调出来虽然很想骂傻逼室友打游戏鬼叫的超级响导致我注意力很难集中,不过终究还是自己抗干扰水平不够,不能怨天尤人A.BeautifulSequence傻逼题,显然若一个......
  • Codeforces Round 642 (Div3)
    K-periodicGarland给定一个长度位\(n\)的\(01\)串,每次操作可以将\(1\)变为\(0\)或者将\(0\)变为\(1\),现在你需要通过操作使得所有\(1\)之间的距离为\(k\),求最少的操作次数,注意全为\(0\)也算\(1<=n<=1e6,1<=k<=n\)\(dp\)/贪心:最大子段和思想方法一:\(dp\)\(O(n)\)状......
  • Codeforces Round 862 (Div. 2)
    CodeforcesRound862(Div.2)链接CodeforcesRound862(Div.2)A题#include<iostream>#include<algorithm>#include<cstdio>#include<cstring>#include<vector>#include<cstring>#include<unordered_set>#includ......
  • Codeforces Round 863 (Div. 3)
    CodeforcesRound863(Div.3)链接CodeforcesRound863(Div.3)A题遍历这个字符串,如果要插入的数第一次小于当前的数,就将数插入到这里,如果到最后都没有插入数,插入到最后#include<iostream>#include<algorithm>#include<cstdio>#include<cstring>#include<vec......
  • Codeforces Round 863 (Div. 3) E题
    题目地址题意:定义数组a包含所有不含数字4的正整数,给出一个n,要求求出数组a中第n个数Solution数位dp+二分,求出[1,mid]中不含数字4的正整数个数,不过因为有可能mid包含4,但是由于贡献是一样的,可以直接把4都变成3,最后处理一下即可intdp[20];inta[20];voidinit(){ dp[0]=1; f......
  • Codeforces Round 863 (Div. 3)
    A.InsertDigit放在第一个比他小的数前面#include<bits/stdc++.h>usingnamespacestd;voidsolve(){intn,d;cin>>n>>d;strings;cin>>s;for(chari:s){if(d>i-'0')cout<<d,d......
  • Codeforces Round 640 (Div. 4) ABCDEFG
    https://codeforces.com/contest/1352不知道怎么的复制过来的代码容易歪,观看效果可能不大好。这场古早div4,大题极其友好,除了E卡空间卡到我爆炸,别的都体验感极好。A.SumofRoundNumbers#include<bits/stdc++.h>usingnamespacestd;typedeflonglongLL;typedefpai......
  • Codeforces Round 863 (Div. 3) A-C 赛后思路复盘
    A(思维)思路:观察样例可知数越大放在前面越优。遍历字符串,判断当前位置的数字和要插入的数字的关系,如果要插入的数大于当前数,那么就插入到当前数的前面。string里有一个insert函数,可以把指定字符串插入到指定下标之前。在原串下标为pos的字符前插入字符串strbasic_string&insert......
  • codeforces round 862
    A.和洛谷上的删数思路一致,后者是找峰顶,这个是找谷底从前到后枚举每一位与要添加的数比大小,如果要添加的数<=该位的数,就继续枚举,否则就将这个数添加在其前面B.需要移动的步数=两个点所在的层数之差的绝对值,只要计算出所在层数就可以一开始没想明白怎么算这个层数,先把每个......