首页 > 其他分享 >Codeforces Round 992 (Div. 2) A~D

Codeforces Round 992 (Div. 2) A~D

时间:2024-12-10 22:56:20浏览次数:7  
标签:temp 992 int void Codeforces dfs ans push Div

目录
广告:starrycoding \(9\) 折优惠码: FV7B04LL

\(E\) 有空再补
构造场, 构造低手掉分.

A

不记得为什么卡了, 居然写了 \(7 \min\).

思路

\(n \le 10^2\), 甚至可以使用 \(n^3\) 算法.
枚举每个 \(a_i\), 判断 \(a_i\) 与 \(\{a_1,a_2,\ldots,a{i-1}\} \cup \{a_{i+1},a_{i+2},\ldots,a_n\}\) 组合后, 是否可以都不被 \(k\) 整除.

复杂度 \(O(n^2)\).

代码

void func(void)
{
	int n,k;
	cin >> n >> k;
	vector<int> a(n+1);
	for(int i=1;i<=n;++i)	cin >> a[i];
	for(int i=1;i<=n;++i)
	{
		int cnt = 0;
		for(int j=1;j<=n;++j)
		{
			if(i == j)	continue;
			int X = abs(a[i]-a[j]);
			if(X % k != 0)	cnt ++;
		}
		if(cnt == n-1)
		{
			cout << "YES\n" << i << '\n';
			return ;
		}
	}
	cout << "NO\n";
}

B

思路

对于操作 \(2\), 每次操作, 若是区间内有 超过一半(向上取整), 的位置有 \(1\), 那么区间内所有数都为 \(1\).

起始必须放置一个 \(1\).
那么我们从 \(1\) 开始放置(俺寻思, 事实上放在中间, 左右轮流放不会影响结果, 不做证明了),

\(1\) 放置后, \(2\) 最多放置在 \(4((1+1) \cdot 2)\) 的位置, 才能满足 \(l \sim r\) 半数有 \(1\),
\(3\) 最多放置在 \(10((4+1) \cdot 2)\).

设当前 \(i\) 的总数为 \(cnt\).
可以得到, 第 \(i\) 个 \(1\), 可以放置在\((cnt+1) \cdot 2\) 的位置.

那么根据上述模拟即可.

复杂度 \(O(\log n)\)

代码

void func(void)
{
	int n;
	cin >> n;
	int X = 1,cnt = 0;
	while(X < n)
	{
		X = (X+1)*2;
		cnt ++;
	}
	cout << cnt+1 << '\n';
}

C

赛时没战意, 这题都没出.
这题不是很好讲, 需要结合图推.

思路

不递减排列是满足条件的.
\(1,2,3,\ldots,n-1,n\), 满足条件.

\[\begin{aligned} S(p) = &\quad \ 1+2+\ldots + n-3 + n-2 + n-1\\ &+ 1 + 2 + \ldots + n-3 + n-2\\ &+ 1 + 2 + \ldots + n-3 \\ &\ \ \vdots \\ &+ 1 + 2 \\ &+ 1\\ \end{aligned} \]

要满足上述内容, 除了 \(n\) 之外的所有数, 两侧至少有一个 大于自己的数.

那么如果我们从 \(n\)开始放置:
\(n-1\) 可以放置在 \(n\) 在左右侧.
\(n-2\) 可以放在 整体 的左右, 但是不能方阵 \(n, n-1\) 之间, 因为会让 \(n-1\) 捕鱼 \(n\) 相邻, 就没有再比它大的数了.

那么从 \(n\) 放置到 \(1\), 每次只能放置在整体的左右.

但是若是从 \(n\) 开始放置, 不好判断字典序顺序(看下述可得).

反向考虑, 从 \(1\) 开始.
下述内容画一画就很明显了
\(1\) 只能防止在最左侧/最右侧.
\(2\) 只能防止在 \(1\) 只内的最左/最右(\(1\) 在左时, \(2\) 放在 \(1\) 由或 最右, 反之亦然. )
\(3\) 只能放在新区间的最左/最右.

那么总共有 \(2^{n-1}\) 种放法.

如果 \(1\) 在最前, 字典序就是前 \(2^{n-1}/2\)(也就是\(2^n-2\)).
否则, 字典序就是 \(2^{n-1}/2+1 \sim 2^{n-1}\).

对于 \(2\), 如果 \(2\) 在新区间最前, 其字典序在此范围的 \(1\sim 2^{n-3}\)
即如果 \(1\) 在最前, \(2\) 在最前的字典序范围 \(1 \sim 2^{n-3}\).
如果 \(1\) 在最后, \(2\) 在最后的字典序范围 \(2^{n-2}+1 \sim 2^{n-1}\).

又因为 \(2^n \gg sizeof(long long)\), 所以只能选择别的方法表示.

根据上述分析, 一次可以排除掉整体区间的 一半, 那么多次就是典型的 \(\log\).
那么可以把 \(2^n\) 和 \(k\) 表示为 \(n\) 和 \(\log{k}\)

具体看代码吧.

复杂度

代码

int qpow(int a,int b)// 快速幂
{
	int res=1;
	while(b)
	{
		if(b&1)res=res*a;
		a=a*a;
		b=b>>1;
	}
	return res;
}

void func(void)
{
	int n,k;
	cin >> n >> k;
	vector<int> a(n+1);
	int l = 1,r = n;
	if(log2(k) > n-1)// c++ 内置log_2函数
	{
		cout << -1 << '\n';
		return ;
	}
	for(int i=1;i<=n-1;++i)
	{
		if(!k || log2(k) <= n-i-1)
		{
			a[l ++] = i;
		}
		else
		{
			a[r --] = i;
			k -= qpow(2,n-i-1);// 能够减去的数小于 10^12
		}
	}
	a[r --] = n;
	for(int i=1;i<=n;++i)	cout << a[i] << ' ';
	cout << '\n';
}

D

沟槽的领接表, 太久没写, 整体clear tle了, 多浪费 \(1h\), 但是多了一种思路.
一题三解, 真有我的.
前置知识: dfs, 领接表.
思路二需要: 埃氏筛.
思路三需要 set, set.lower_bound().

三解太耗精力, 之后可能会补充吧.

解法 \(1\)

思路

比较俺寻思, 但是感觉更好理解.

  • 要求相邻两数差不为质数, 偶数 除了\(2\), 都不为质数.
  • 总共只能使用 \(2\cdot n\) 个点.

先假设一条 \(5\) 条的链, 我们只放奇数, 那么:
alt text
是可以满足情况的.

但是若是点很少:
alt text
是放不下的.

再考虑花形:
alt text
三个点的链也属于花形.

整个图可以可以视作若干个上述小单元的组合(链和花).

每个小单元则只能使用 \(cnt_{点总数}\cdot 2\)个数.

而\(2\)不能使用, 每个单元必然有一个数不能放置.

如果填入 \(1\), 那么该单元就可以放满了:
alt text

那么从根节点出发, 每次优先放 \(1\), 其次放差 \(2\) 以外同奇偶性的数.

本质还是解法\(1\), 只是实现不同.

代码

void dfs(int p,int lp)
{
	if(a[p].size() <= 1)	return ;
	int cnt = a[p].size() - 1;
	stack<int> X;
	if(ans[p]&1)
	{
		if(st2.lower_bound(ans[p]+1) != st2.end() && *st2.lower_bound(ans[p]+1) == ans[p]+1)
		{
			X.push(ans[p]+1);
			st2.erase(ans[p]+1);
		}
		vector<int> stp;
		while(X.size() != cnt)
		{
			int temp = *st1.begin();	st1.erase(temp);
			if(temp != ans[p] + 2 && temp != ans[p]-2)	X.push(temp); 
			else	stp.push_back(temp);
		}
		for(auto &i : stp)	st1.insert(i);
	}
	else
	{
		if(st1.lower_bound(ans[p]+1) != st1.end() && *st1.lower_bound(ans[p]+1) == ans[p]+1)
		{
			X.push(ans[p]+1);
			st1.erase(ans[p]+1);
		}
		vector<int> stp;
		while(X.size() != cnt)
		{
			int temp = *st2.begin();	st2.erase(temp);
			if(temp != ans[p] + 2 && temp != ans[p]-2)	X.push(temp);
			else	stp.push_back(temp);
		}
		for(auto &i : stp)	st2.insert(i);
	}
	for(auto &i : a[p])
	{
		if(i == lp)	continue;
		ans[i] = X.top(); 
		X.pop();
		
	}
	for(auto &i : a[p])
	{
		if(i == lp)	continue;
		dfs(i,p);
	}
}

void func(void)
{
	int n;
	cin >> n;
	for(int i=2;i<=n<<1;++i)
	{
		(i&1) == 1 ? st1.insert(i) : st2.insert(i);
	}
	for(int i=1;i<=n;++i)	a[i].clear();
	int x,y;
	for(int i=1;i<n;++i)
	{
		cin >> x >> y;
		a[x].push_back(y);
		a[y].push_back(x);
	}
	a[1].push_back(0);
	ans[1] = 1;
	dfs(1,0);
	for(int i=1;i<=n;++i)	cout << ans[i] << ' ';
	cout << '\n';
}

解法 \(2\)

从此视频学习: Codeforces Round 992 (Div. 2) 题目讲解 ABCDE (CF2040)

两个解法一直在 \(tle\), 只能找了题解.

思路

和解法 \(1\) 类似, 每个小单元最多使用 \(2\cdot k\) 个数. 而用 \(1\) 补 \(2\), 同奇偶性的数刚好在范围内.

代码

int X;
vector<int> a[N],ans(N);

void dfs(int p,int lp)
{	
	ans[p] = X --;
	int cnt = 0;
	for(auto &i : a[p])
	{
		if(i == lp)	continue;
		if(ans[p]-X == 2) X -= 2;
		else if(ans[p]-X != 1 && (ans[p]-X)&1)	X --;
		cnt ++;
		dfs(i,p);
	}
	int len = a[p].size();
}

void func(void)
{
	int n;
	cin >> n;
	for(int i=1;i<=n;++i)	a[i].clear();
	int x,y;
	for(int i=1;i<n;++i)
	{
		cin >> x >> y;
		a[x].push_back(y);
		a[y].push_back(x);
	}
	X = n<<1;
	dfs(1,0);
	for(int i=1;i<=n;++i)	cout << ans[i] << ' ';
	cout << '\n';
}

解法 \(3\)

起始思路, 根本没想到是领接表问题.

思路

既然每条边差都为非素数, 那么dfs到每个点, 给子节点赋值 \(+\) 非素数即可. 复杂度懒得证明了.

代码

#include<bits/stdc++.h>
#define Start cin.tie(0), cout.tie(0), ios::sync_with_stdio(false)
#define PII pair<int,int> 
#define x first
#define y second
#define ull unsigned long long
#define ll long long
using namespace std;

const int M = 1000000007;
const int N = 2e5 + 10;

int len;
bitset<N<<1> vis;
vector<int> v(1,1),pri,a[N],ans(N);

void func(void);

void dfs(int p,int lp)
{
	int X = 0;
	for(auto &i : a[p])
	{
		if(i == lp)	continue;
		while(vis[ans[p]+v[X]])	X ++;
		ans[i] = ans[p] + v[X];
		vis[ans[i]] = true;
		dfs(i,p);
	}
}

signed main(void)
{
	Start;
	int n = N<<1;
	for(int i=2;i<=n;++i)
	{
		if(!vis[i])	pri.push_back(i);
		for(int j=0;pri[j]<=n/i;++j)
		{
			v.push_back(pri[j] * i);
			vis[pri[j] * i] = true;
			if(i % pri[j] == 0)	break;
		}
	}
	len = v.size();
	sort(v.begin(),v.end());
	int _ = 1;
	cin >> _;
	while(_--)	func();
	return 0;
}

void func(void)
{
	int n;
	cin >> n;
	vis.reset();
	for(int i=1;i<=n;++i)	a[i].clear();
	int x,y;
	for(int i=1;i<n;++i)
	{
		cin >> x >> y;
		a[x].push_back(y);
		a[y].push_back(x);
	}
	ans[1] = 1;
	dfs(1,0);
	for(int i=1;i<=n;++i)	cout << ans[i] << ' ';
	cout << '\n';
}

标签:temp,992,int,void,Codeforces,dfs,ans,push,Div
From: https://www.cnblogs.com/zerocloud01/p/18598166

相关文章

  • HTML5期末大作业:用DIV+CSS技术设计的网页与实现(剪纸传统文化网页设计主题)
    ......
  • 如果列表元素li的兄弟元素为div,会产生什么情况?
    如果列表元素<li>的兄弟元素是<div>,这在HTML中是无效的。<li>元素(列表项)必须是<ul>(无序列表),<ol>(有序列表),或<menu>元素的直接子元素。它们不能与<div>或其他元素作为同一父元素的兄弟元素存在。浏览器会尝试以不同的方式来处理这种无效的HTML结构,这取决于具体的......
  • Codeforces Round 992 (Div. 2) 解题报告
    比赛地址:https://codeforces.com/contest/2040A.GameofDivision题目https://codeforces.com/contest/2040/problem/A题意给你一个长度为\(n\)的整数数组\(a_1,a_2,\ldots,a_n\)和一个整数数组\(k\)。两个玩家正在玩一个游戏。第一个玩家选择一个索引\(1\l......
  • codeforces常规线段树专项练习
    以下是常规线段树模板,支持单点赋值set、单点增加add、区间查询find、查找第一个满足条件元素findFirst、查找最后一个满足条件元素findLast。template<classVal>structSegTree{intn=0;std::vector<Val>val;voidinit(int_n,Valv=Val()){st......
  • 【CodeForces训练记录】Codeforces Round 991 (Div. 3)
    训练情况赛后反思打到D题摆了,连续两道数位的智慧题?可能我比较缺观察A题记录一下字符串的长度,能塞到第一行的尽量塞到第一行。#include<bits/stdc++.h>//#defineintlonglong#defineendl'\n'usingnamespacestd;voidsolve(){intn,m;cin>>n>>m;vect......
  • CF补题 964-Div.4
    CF补题964-Div.4-20241206Dashboard-CodeforcesRound964(Div.4)-CodeforcesA:题目大意:给定一个两位数正整数n,求其位数之和#include<stdio.h>intmain(){intn;scanf("%d",&n);while(n--){intx,sum=0;scanf("%d&quo......
  • 在固定宽度的div下,怎么让字体自适应大小,不超出宽度,也不要换行
    在固定宽度div下实现字体自适应大小,防止文本超出宽度且不换行,可以使用几种方法:1.使用vw和vh单位:这种方法允许你根据视口宽度设置字体大小。例如,font-size:2vw;表示字体大小为视口宽度的2%。这可以确保字体大小与div的宽度成比例缩放。但是,这种方法的缺点在于字体......
  • round 964 div4
    A.A+BAgain?给定一个两位数正整数$$$n$$$,求其位数之和。将每位数取出相加即可`#includeincludeconstintN=114514;inta[N];intn;intt;usingnamespacestd;intmain(){cin>>t;while(t--){cin>>n;intsum=0;while(n!=0){sum+=n%10;n/......
  • Codeforces Round 991 (Div. 3)
    CodeforcesRound991(Div.3)2024.12.6rank1559rating1314->1381A模拟B给定一数组,你可以任意操作:a[i-1]+1&&a[i+1]-1或者a[i-1]-1&&a[i+1]+1。问是否可以使数组全为相同的数字。C给定一大数,可任意将2->4,3->9,问是否可被9整除。D给定一大数,你可任意操作:将某......
  • Codeforces Round 991 (Div. 3)
    CodeforcesRound991(Div.3)2024.12.6rank1559rating1314->1381A模拟B给定一数组,你可以任意操作:a[i-1]+1&&a[i+1]-1或者a[i-1]-1&&a[i+1]+1。问是否可以使数组全为相同的数字。C给定一大数,可任意将2->4,3->9,问是否可被9整除。D给定一大数,你可任意操作......