Codeforces Round # 655 (Div. 2) 题解

A

原题链接
题意:T组数组,每组一个n,现在让你构造一个长度为n的数组,要求数组满足对所有的1<=x,y,z<=n,ax+ay ≠ az (a不一定不同)

题解:因为是spj,我们只需要构造出一个长度为n,元素全为1的数组就行了

#include < bits / stdc ++. h > 
using namespace std ; 
int n , k ;
 
int main () {
	cin >> n ;
	for ( int i = 1 ; i <= n ; ++ i ) { 
		scanf ( "% d" , & k );
		for ( int j = 1 ; j <= k ; j ++) { 
			if ( j ! = k ) printf ( "1" );
			else printf ( "1 \ n" );
		}
	}	
	return 0 ; 
}

B

原题链接
题意:T组数据,每组一个n,现在需要你找到一个a和一个b,使得 a + b = n并且LCM(a,b) 最小

题解:
考虑n的奇偶性:
1.如果n是偶数,显然我们可以构造出a=b=n/2使得LCM最小
2.如果n是奇数,因为n的大小最多是1e9,可以考虑从3往上找,找到第一个n的因子k,则a=n/k,b=n-a
如果找不到,说明n是个质数,则a=1,b=n-1

复杂度: O ( n ) O(\sqrt[]{n}) O(n )

#include <bits/stdc++.h>
using namespace std;
int n,T;

int main(){
	cin>>T;
	while(T--){
		scanf("%d",&n);
		if(n % 2==0){
			printf("%d %d\n",n/2,n/2);
			continue;
		}
		int flag=0;
		for (int i=3;i<=sqrt(n);i++){
			if(n % i == 0){
				flag = 1;
				printf("%d %d\n",n/i,n-(n/i));
				break;
			}
		}
		if(!flag) printf("1 %d\n",n-1);
	}	
	return 0;
}

C

原题链接
题意:T组数据,每组一个n,之后是一个长度为n的数组a,数组a是一个n的排列。对于每组数据,现在你可以对数组做如下操作:把[L,R]这一个连续区间的数改变位置(且要保证改变后区间中的每个数不能在原来的位置上),如:[1,2,3]可以变化为[3,1,2],但不能是[3,2,1]。现在问最少需要几次这样的区间变化操作使得数组a有序

题解:先看几个特例:
(设至少需要k次操作)
1.当数组开始有序,则k=0
2.当数组是一个完全乱序(即每个a[i]都不在i位置上),则我们只需要1次对于区间[1,n]的操作就可以使得有序
3.不是完全乱序。因为每次操作针对的是一个连续的区间,所以我们可以先将问题简化,设定两个指针l,r,初始时l=1,r=n,如果从左到右a[i] = i,则l++,如果从右到左a[i] = i,则r–,则我们现在需要操作的区间就是[l,r]这个区间了。

然后再观察[l,r]这个区间
由2我们可以知道,如果[l,r]这个区间完全乱序,则k=1,如果[l,r]这个区间不是完全乱序,打个比方:1,2,5,4,3,6,7,[5,4,3]这个区间,我们只需要先操作一次变为[4,5,3],再操作一次变为[3,4,5]就可以了,则k=2。

#include <bits/stdc++.h>
using namespace std ; 
const int maxn = 2e5 + 10 ;  
int n , T ;
int a [ maxn ], b [ maxn ];

int main () {
	cin >> T ;
	while ( T --) {
		scanf ( "%d" , &n );
		int cnt = 0 ;
		for ( int i = 1 ; i <= n ; i ++) { 
			scanf ( "%d" , & a [ i ]);
			if ( a [ i ] == i ) cnt ++; 
		}
		if ( cnt == n ) { 
			puts ( "0" ); continue ;
		}
		if ( cnt == 0 ) { 
			puts ( "1" ); continue ;
		}
		int l = 1 , r = n ;
		while ( a [ l ] == l ) l ++; 
		while ( a [ r ] == r ) r --; 
		cnt = 0 ;
		for ( int i = l ; i <= r ; i ++) { 
			if ( a [ i ] == i ) cnt ++;  
		}
		if ( cnt != 0 ) puts("2");
		else puts ("1");
	}	
	return 0 ; 
}
* /

D

原题链接
题意:给你一个奇数长度为n的循环数组(首位相连接,a[1]与a[n]相邻),现在进行若干次操作,每次选数组中任意一个数,然后用它相邻两个数之和替换掉它,问最后剩下的这个数最大是多少

题解:

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值