「KDOI-06-J」翻转与反转

5 篇文章 0 订阅

「KDOI-06-J」翻转与反转
洛谷:https://www.luogu.com.cn/problem/P9741?contestId=125612
在这里插入图片描述
输入 #1
3
1 1 1
输出 #1
0 0 1
输入 #2
8
1 0 1 1 1 0 0 1
输出 #2
0 1 0 1 1 1 1 0
在这里插入图片描述

思路1:
因为数据在2e6如果进行暴力的话会超时,所以就需要找规律,也就变成了一个思维问题。
对于第i个数,我们很容易知道需要对它操作n-i+1次
对于第1个变换(前i个数交换次序),可以发现,第i位在进行第一次操作时向前移动了i-1位,而第二次操作时向后移动i位,第三次又向前移动了i-1位,那么就可以推出来,操作两次共往后移动1位,如果有剩余(即需要操作奇数次),那么就再往前移动了i-1位就可以了。
对于第2个变换(数值翻转),操作为奇数次时,这一位上会发生变换,反之操作偶数次时,这一位上不会变换。

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define N 2e5+5
int a[2000001];
int b[2000001]; 
void solve(){
	int n;
	cin>>n;
	for(int i=1;i<=n;i++){
		cin>>a[i];//存储原来的数据 
	}
	for(int i=1;i<=n;i++){
		int p=n-i+1;//需要操作的次数
		int ans=0;//需要变换的位置(需要向前/后移多少位)
		if(p%2==0){
			ans=p/2;
			b[ans+i]=a[i];
		}
		else{
			p--;
			ans=p/2-i+1;//ans先向后移动p/2位,再向前移动i-1位
			if(a[i]==0){
				b[ans+i]=1;
			}
			else
			b[ans+i]=0;
		}
	}
	for(int i=1;i<=n;i++){
		cout<<b[i]<<" ";//存储变换之后的数据 
	}
}
int main(){
	int t=1;
	while(t--){
		solve();
	}
	return 0;
}

思路2:
不管进行到第几次操作(假设为i)那么i这个位置上的数现在必定排列在第一位,那么在第i+1次的时候原来i位置上的数就改变到i+1的位置上了
n-2 n-3
n-1 n-2
n n-1
(像这样排列一样)
那么变换到最后一定为n n-2 n-4 … 1 … n-3 n-1 中间一定为1
并且对于前半段(即1之前的元素)一定操作了奇数次,所以一定需要进行取反的,对于1即1后面的数就需要进行讨论了:
当n为偶数时,1的前一位一定会是2,那么后半段开始的元素就需要从3开始,并且1这一位一共操作了n-i+1次即n次,是偶数次,所以不需要进行变换。
当n为奇数时,1的前一位一定会是3,那么后半段开始的元素就需要从2开始,并且1这一位一共操作了n-i+1次即n次,是奇数次,所以需要进行变换。
代码如下:

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define N 2e5+5
int a[2000001];
void solve(){
	int n;
	cin>>n;
	for(int i=1;i<=n;i++){
		cin>>a[i];
	}
	for(int i=n;i>1;i-=2){
		cout<<!a[i]<<" ";
	}
	if(n%2==0){
		cout<<a[1]<<" ";
		for(int i=3;i<=n-1;i+=2){
			cout<<a[i]<<" ";
		}
	}
	else{
		cout<<!a[1]<<" ";
		for(int i=2;i<=n-1;i+=2){
			cout<<a[i]<<" ";
		}
	}
}
int main(){
	int t=1;
	while(t--){
		solve();
	}
	return 0;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值