6.30 Codeforces Round 练习

  • 题目:
    给你一个数组A,让你构造一个数组B,使得A[1] * B[1] + A[2] * B[2] + …A[n] * B[n] = 0,A数组和B数组里面都没有0?
  • 思路:
    如果n是偶数就对于每一个i直接构造B[i]和B[i + 1]使得B[i] * A[i] = A[i + 1] * B[i],求A[i]和A[i +1]的最小公倍数,然后除一下就行
    如果是奇数的话,就让最后三个构造出一个A[n - 2] * x + A[n - 1] * y = A[n] * z,其他的就按偶数来写就行,
    这道题的代码写的有点啰嗦,不太好
  • 代码:
#include <bits/stdc++.h>
#define fi first
#define se second
#define endl '\n'
#define all(x) x.begin(),x.end()
#define pb push_back
#define PII pair<int,int>
#define int long long 
#define ios ios::sync_with_stdio(false); cin.tie(0); cout.tie(0)
using namespace std;
const int N = 2e5 + 100,mod = 1e9 + 7;

int gcd(int a,int b)
{
	if(b == 0) return a;
	
	return gcd(b,a % b);
}
int lcm(int a,int b)
{
	int w = a / gcd((int)a,(int)b) * b;
	return w;
}
void solve()
{ 
	int n; cin >> n;
	vector<int> a(n + 1);
	for(int i = 1;i <= n;i ++ ) cin >> a[i];
	vector<int> res;
	for(int i = 1;i <= n;i += 2)
	{
		if(n % 2 == 1 && i == n - 2)
		{
			int f = 0;
		int k = a[n - 2] + a[n - 1];
		int q = abs(k);
		if(q == 0)
		{
			 q = abs(k + a[n - 1]);
			 f = 1;
		}
		int w = abs(a[n]);
		int s = lcm(q,w);
	//	cout << s << ' ' << q << ' ' << w << endl;
		if(f)
		{
			if(k + a[n - 1] > 0 && a[n] > 0) 
		{
			res.pb(s / q),res.pb(s / q * 2);
			res.pb(s / w * -1);
		}
		else if(k + a[n - 1] > 0 || a[n] > 0)
		{
			 res.pb(s / q),res.pb(s / q * 2);
			 res.pb(s / w);
		}
	 	else if(k + a[n - 1] < 0 && a[n] < 0)
	 	{
	 		res.pb(s / q),res.pb(s / q * 2);
			res.pb(s / w * -1);
		}
		}
		else
		{
				if(k > 0 && a[n] > 0) 
		{
			res.pb(s / q),res.pb(s / q );
			res.pb(s / w * -1);
		}
		else if(k  > 0 || a[n] > 0)
		{
			 res.pb(s / q),res.pb(s / q );
			 res.pb(s / w);
		}
	 	else if(k < 0 && a[n] < 0)
	 	{
	 		res.pb(s / q),res.pb(s / q );
			res.pb(s / w * -1);
		}
		}
		
		
		break;
			
		}
		
		int q = abs(a[i]),w = abs(a[i + 1]);
		int s = lcm(q,w);
		if(a[i] > 0 && a[i + 1] > 0) res.pb(s / q),res.pb(s / w * -1);
		else if(a[i] > 0 || a[i + 1] > 0) res.pb(s / q),res.pb(s / w);
	 	else if(a[i] < 0 && a[i + 1] < 0) res.pb(s / q),res.pb(s / w * -1);
	}	
	
	for(int i = 0;i < res.size();i ++ )
	cout << res[i] << ' ';
	
	cout << endl;
	
}

signed main() 
{
	ios;int T; cin >> T;
	while(T -- ) solve();

    return 0;
}
  • 题目:
    给你a,b,x,你可以执行这个操作 a = abs(a - b),或者b = abs(a - b),问你有没有可能使得 a 或者 b 等于x
  • 思路:
    观察发现 x 如果在[a , b]之间的话,就可以用一个等差数列来求,x是否在这个区间,公差为 - min(a,b),首项为 max(a,b) 如果x不在这个范围内的话,就让b不断的靠近a,然后把然后使得b接替原来a的位置,a就等于b - a,这个操作也是可以用等差数列来求解的
  • 代码:
#include <bits/stdc++.h>
#define fi first
#define se second
#define endl '\n'
#define all(x) x.begin(),x.end()
#define pb push_back
#define PII pair<int,int>
#define int long long 
#define ios ios::sync_with_stdio(false); cin.tie(0); cout.tie(0)
using namespace std;
const int N = 2e5 + 100,mod = 1e9 + 7;

bool check(int a,int b,int x)
{
	if(a == 0 || b == 0) return false;
	if(a == x || b == x) return true;
	if(x < a)
	{
		int k = b / a;
		int w = a + b - a * k;
		int c = w - a;
		b = a;
		a = c;
		if(check(a,b,x)) return true;
		return false;
	}
	else if(x >= a && x <= b)
	{
		int w = (a + b - x) / a;
		int s = a + b - w * a;
		
		if(s == x) return true;
		else return false;  
	}
	else 
	return false;
	
	return false;
}
void solve()
{ 
	int a,b,x;cin >> a >> b >> x;
	if(a > b) swap(a,b);

	if(check(a,b,x)) cout << "YES" << endl;
	else cout << "NO" << endl; 

	
}

signed main() 
{
	ios;int T; cin >> T;
	while(T -- ) solve();

    return 0;
}
  • 题目:
    有n个人,第i个人有i元钱,并且想要这个人参加聚会这个人的规矩就是 最多a[i]个人比他富,有b[i]个人比他穷,问你最多能邀请几个人来参加聚会
  • 思路:
    首先,第i个人有i元钱,这样的话就可以二分枚举人数,观察发现,如果按照钱的数量来从左到右排列的话,发现A[i]是一个递减序列,B[i]是一个递增序列,然后直接暴力枚举符合人数就行,时间复杂度O(n * log(n))
  • 代码:
#include <bits/stdc++.h>
#define fi first
#define se second
#define endl '\n'
#define all(x) x.begin(),x.end()
#define pb push_back
#define PII pair<int,int>
#define int long long 
#define ios ios::sync_with_stdio(false); cin.tie(0); cout.tie(0)
using namespace std;
const int N = 2e5 + 100,mod = 1e9 + 7;
int a[N],b[N];
int n;
bool check(int mid)
{
	int d = 0;
	int q1 = mid - 1;
	int q2 = 0;
	for(int i = 1;i <= n;i ++ )
	{
		if(a[i] >= q1 && b[i] >= q2)
		{
			d++;
			q1--,q2++;
		}
	}
	
	if(d >= mid) return true;
	return false;
}
void solve()
{ 
	cin >> n;
	for(int i = 1;i <= n;i ++ ) cin >> a[i] >> b[i];
	
	int l = 1,r = n;
	while(l <= r)
	{
		int mid = l + r >> 1;
		
		if(check(mid))
		l = mid + 1;
		else
		r = mid - 1;
	}
	
	cout << r << endl;

	
}

signed main() 
{
	ios;int T; cin >> T;
	while(T -- ) solve();

    return 0;
}
  • 题目:
    有n个点,m条边,每次都给你两个点a,b,操作1:如果a,b不在一个联通块里面,就连接一下,操作2:如果a,b在一个连通块里面,那么就可以连接其他的未加入连通块的点,问你最大的连通块有多少个点?
  • 思路:
    假设到第i条边的时候有cnt个操作2,那答案就是前cnt +1个大的连通块相加.并查集
  • 代码:
#include <bits/stdc++.h>
#define fi first
#define se second
#define endl '\n'
#define all(x) x.begin(),x.end()
#define pb push_back
#define PII pair<int,int>
#define int long long 
#define ios ios::sync_with_stdio(false); cin.tie(0); cout.tie(0)
using namespace std;
const int N = 1e3 + 100,mod = 1e9 + 7;
int p[N],num[N];
int cnt = 1;
int n,d;
int find(int x)
{
	if(x != p[x]) p[x] = find(p[x]);
	
	return p[x];
}
bool cmp(int a,int b)
{
	return a > b;
}
void add(int a,int b)
{
	a = find(a);
	b = find(b);
	
	if(a != b)
	{
	p[a] = b;
	num[b] += num[a];
	}
	else
	cnt++;
	
	vector<int> res;
	
	for(int i = 1;i <= n;i ++ )
	if(p[i] == i)
	res.pb(num[i]);
	
	sort(all(res),cmp);
	int sum = 0;
	int k = res.size();
	for(int i = 0;i < min(cnt,k);i ++ )
	sum += res[i];
	
	//cout << cnt << endl;
	cout << sum - 1 << endl;
	
	
	
}
void solve()
{ 
	 cin >> n >> d;
	for(int i = 1;i <= n;i ++ ) 
	{
		p[i] = i; num[i] = 1;
	}
	
	
	for(int i = 1;i <= d;i ++ )
	{
		int a,b; cin >> a >> b;
		add(a,b);
		
	}
	
	 
}

signed main() 
{
	ios;int T = 1;
	while(T -- ) solve();

    return 0;
}
  • 题目:
    有两个地图,n个人,每个人在不同的地图里面都有自己独特的战斗力,每个人可以挑地图战斗,进行n - 1次挑战后,只会留下来一个胜利的人,对于每一个人都询问一下他有没有可能是这个胜利的人.
  • 思路:
    这个题是今天唯一没有写出来的题,就是思维懂了,但是代码能力这方面不行,
    就是a数组排序如果小的是最后的wiiner,那比这个数字大的都有可能是wIner,同理也对b排个序,然后走两遍dfs,最后一定是一个环,遍历这个环就行
    就是这个没想到咋用代码实现.
  • 代码:(借鉴别人的)
#include <bits/stdc++.h>
#define fi first
#define se second
#define endl '\n'
#define all(x) x.begin(),x.end()
#define pb push_back
#define PII pair<int,int>
#define int long long 
#define ios ios::sync_with_stdio(false); cin.tie(0); cout.tie(0)
using namespace std;
const int N = 2e5 + 100,mod = 1e9 + 7;
int res[N];
vector<int> d[N];
vector<PII> a,b;
int n; 
void dfs(int u)
{
	res[u] = 1;
	
	for(auto x:d[u])
	{
		if(!res[x])
		dfs(x);
	}
}
void init()
{
		for(int i = 0;i <= n;i ++ )
	{
		a.clear(),b.clear();
		d[i].clear();
		res[i] = 0;
	}
}
void solve()
{ 
	cin >> n;
	init();
	for(int i = 1;i <= n;i ++ )
	{
		int x;cin >> x;
		a.pb({x,i}); 
	}
	
	for(int i = 1;i <= n;i ++ )
	{
		int x; cin >> x;
		b.pb({x,i});
	}
	sort(all(a)); sort(all(b));
	
	for(int i = 0;i < n - 1;i ++ )
	{
		d[a[i].se].pb(a[i + 1].se);
		d[b[i].se].pb(b[i + 1].se);
	}
	
	dfs(a[n - 1].se); dfs(b[n - 1].se);
	
	for(int i = 1;i <= n;i ++ ) cout << res[i];
	cout << endl;
	
	
	
}

signed main() 
{
	ios;int T; cin >> T;
	while(T -- ) solve();

    return 0;
}
Codeforces Round 887是一个程序设计竞赛活动,由Codeforces组织举办。根据引用中的代码,该竞赛的题目要求解决一个序列操作的问题。给定一个长度为n的序列,通过执行一系列操作,使得序列变得非sorted,即非严格递增。具体操作是将序列中[1, i]范围内的数字全部加一,同时将[i+1, n]范围内的数字全部减一。问题要求求解最少需要执行多少次操作才能达到要求。 引用中的代码给出了解决这个问题的实现。代码首先读入序列的长度n和序列a。然后通过判断序列是否已经是非sorted,如果是则直接输出0。接下来,代码遍历序列,求出相邻两个数字的差的最小值。最后,计算出最少需要执行的操作次数,并输出结果。 需要注意的是,引用中的代码只是给出了解决问题的一种实现方式,并不代表Codeforces Round 887的具体题目和解答。要了解该竞赛的具体信息,需要参考Codeforces官方网站或相关资料。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* *3* [Codeforces Round 887 (Div. 2)](https://blog.csdn.net/qq_36545889/article/details/131905067)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 100%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值