Codeforces Round 889 (Div. 2)(A~C2)

A. Dalton the Teacher

题目大意: 给n个整数 a1 ,a2 ,a3 , .. an 其满足1-n的排列 ,一次操作为交换 ai ,aj (1 <= i , j , <= n)

问最低多少次交换可让所以满足 ai != i;

首先如果是sum个不同的话,如果sum 为偶数 那么交换次数最少显然为sum / 2;

那么奇数的话,交换sum- 1 个次数为(sum - 1) / 2 , 再交换最后一个 那么 为 (sum - 1) /  2 + 1次

那么结果就可以写成(sum + 1) / 2

ac代码:

#include<iostream>
#include<algorithm>
#include<map>
#include<vector>
#include<set>
#define int long long
using namespace std;

void solve(){
	
	int n;
	cin >> n;
	int sum = 0 ;
	for(int i = 1 ; i <= n ; i ++){
		int t;
		cin >> t;
		if(t == i) sum ++;
	}
	cout << ((sum + 1 )/ 2) << "\n";
	
}

signed main()
{
	ios::sync_with_stdio(0);
	cin.tie(0),cout.tie(0);
	int T;
	cin >> T;
	while(T--){
		solve();
	}
	
	
	
	
}  

  B. Longest Divisors Interval

题目大意:

给定一个正整数 n,求一个正整数区间 [l,r]的最大大小,使得区间中的每一个 i(即 l≤i≤r≤n), n都是 i的倍数。区间[l,r]的大小为r−l+1(即与属于区间的整数个数重合)。

首先n的范围为1e18

因为连续都是其倍数 所以我们可以枚举22个数(22的阶乘大于1e18) 

但不知道为什么赛时的时候噶了,然后开大范围才过的

ac代码就是

#include<iostream>
#include<algorithm>
#include<map>
#include<vector>
#include<set>
#define int long long
using namespace std;

void solve(){
	int n;
	cin >> n;
	int sum = 0;
	int res = 0;
	for(int i = 1 ; i <= 100 ; i ++){
		if(n % i == 0){
			sum++;
		}
		else{
			res = max(res,sum);
			sum = 0;
		}
	}
	cout << res << "\n";
	
}

signed main()
{
	ios::sync_with_stdio(0);
	cin.tie(0),cout.tie(0);
	int T;
	cin >> T;
	while(T--){
		solve();
	}
	
	
	
	
}  

C1,C2. Dual (Hard Version))

很有意思的题

给你一个整数数组 a1,a2,…,an正数、负数或 00)。你可以对数组进行多次运算(可能有 0次运算)。

-20 <= ai <= 20;

在一次操作中,您可以选择 i,j 让 ai = ai + aj。

使数组在最多31次运算中不递减。您不需要尽量减少运算次数。

首先我们可以考虑一下如果an全部大于等于0 , 或者小于等于 0 怎么说 , 那么显然正数就直接前缀和负数就可以后缀和 ,那么次数就是n - 1次

剩下的次数就是把数全部变成正或者负,那么变正数还是负数呢

变成正数的次数就是 数列中负数的个数以及让max(正) 变的 大于abs(min(负))的次数

变成全部负数的次数就是数列中正的个数以及让abs(min(负)) 大于max(正)的次数

选择小的次数去变

ac代码

#include <bits/stdc++.h>
#define int long long
#define fi first
#define se second
using namespace std;
const int N = 2e5 + 10;
int n;
int a[N];
void solve(){
	int f = 0 ;
	int z = 0;
	//vector<int> a (n + 1);
	vector<pair<int , int >> b;
	int  n;
	cin >> n;
	int zmax = -1;
	int fmin = 21;
	int j = 0 , x = 0 ;
	for(int i = 1 ; i <= n ; i ++){
		cin >> a[i];
		if(a[i] > 0) z++;
		if(a[i] < 0) f ++;
		
		if(a[i] > zmax ) {
			zmax = a[i] , j = i;
		}
		if(a[i] < fmin) {
			fmin = a[i] , x =  i;
		}
	}
	
	int res = 0;
	if(z == 0 ){
		cout << n - 1 << "\n";
		for(int i = n - 1; i >= 1; i --){
			cout << i  << " "  << i + 1 << "\n";
		}
	}
	else if(f == 0){
		cout << n  - 1 << "\n";
		for(int i  = 1; i <= n - 1 ; i ++){
			cout << i + 1 << " " << i << "\n";
		}
	}
	else {
		
		
		int z1 =  0 ;
		int f1 = 0 ;
		int znum = zmax;
		int	fnum = fmin;
		while(znum < abs(fmin)){
			z1 ++;
			znum *= 2;
		}
		while(abs(fnum) < zmax){
			f1 ++;
			fnum  *= 2;
		}
		//cout << z1 << " " << z << " " << f1 << " " << f << "\n";
		if(f1 + z >= z1 + f ){
			
			while(zmax < abs(fmin)){
				res ++;
				zmax *= 2;
				b.push_back({j,j});
			}
			
			for(int i = 1 ; i <= n ; i ++){
				if(a[i] < 0 ) b.push_back({i,j}),res++;;
				
			}
			cout << res + n - 1<< "\n";
			for(auto [t,v] : b){
				cout << t << " " << v <<  "\n";
			}
			for(int i = 1 ; i < n ; i ++){
				cout << i + 1 << " " << i << "\n";
			}
			
		}
		else{
			while(abs(fmin) < zmax){
				res ++;
				fmin  *= 2;
				b.push_back({x,x});
			}
			for(int i = 1 ; i <=  n ; i ++){
				if(a[i] > 0 ) b.push_back({i,x}),res++;;
				
			}
			cout << res + n - 1 << "\n";
			for(auto [t,v] : b){
				cout << t << " " << v << "\n";
			}
			for(int i = n - 1 ; i >= 1  ; i --){
				cout << i  << " " << i + 1 << "\n";
			}
			
			
		}
	}

	
	
	
	
	
	
}
signed main()
{
	//ios::sync_with_stdio(0);
	//cin.tie(0),cout.tie(0);
	int T;
	cin >> T;
	while(T--){
		solve();
	}
	return 0;
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值