CodeForces - 899C Dividing the numbers 思维

http://codeforces.com/problemset/problem/899/C

题意:给你1~n连续的n个数。将这n个数分成两拨,要求两拨之差的绝对值k最小。求出这个最小的绝对值,并输出其中的一拨的数字。

题解:首先要想清楚这个k非零即一

先将问题分解成两类:奇数和偶数。

先看最简单的偶数:

由于可以组成如1,n以及2,n-1这样的数对。

①如果n%4==0。那么就有偶数组上述数对,直接构造输出即可。k就等于0。

②如果n%4!=0。那么两拨分完之后还剩下一个上述数对,那么一拨一个。很容易想到要剩下的是n/2和n/2+1。那么k等于1。

在看奇数:

①如果(n+1)%4==0。那么k=0。为什么?

以n=7为例,在分好1,7,2,6和3,5,4之后。相当于这两拨的差距在2,6和4。第一拨多了n+1,第二拨多了(n+1)/2。也就是说第一拨比第二拨多了(n+1)/2。那么第一拨就要分出(n+1)/4给第二拨(这也是为什么要满足(n+1)%4==0)。可以发现就是要交换上面的6和4,让2和4凑成一对,这样(n+1)/4和(n+1)/2凑成一对。这样k等于0。

②如果n%4!=0。那么k就不会等于0了,那么肯定存在k=1的解。

以5为例,分成1,5和2,4,3。这里是1和3互换,原理同上。

代码:

#include<bits/stdc++.h>
#define debug cout<<"aaa"<<endl
#define d(a) cout<<a<<endl
#define pb push_back
#define mem(a,b) memset(a,b,sizeof(a))
#define LL long long
#define lson l,mid,root<<1
#define rson mid+1,r,root<<1|1
#define MIN_INT (-2147483647-1)
#define MAX_INT 2147483647
#define MAX_LL 9223372036854775807i64
#define MIN_LL (-9223372036854775807i64-1)
using namespace std;

const int N = 100000 + 5;
const int M = N * N + 5;
const int mod = 1000000000 + 7;
const int INF = 0x3f3f3f3f;
const double eps = 1e-8;

int main(){
	int n;
	if(n%2==0){
		if(n%4==0){
			cout<<0<<endl;
			cout<<n/4*2<<" ";
			for(int i=1;i<=n/4;i++){
				cout<<i<<" "<<n-i+1<<" ";
			}
			cout<<endl;
		}
		else{
			cout<<1<<endl;
			cout<<n/4*2+1<<" ";
			for(int i=1;i<=n/4;i++){
				cout<<i<<" "<<n-i+1<<" ";
			}
			cout<<n/2<<endl;
		}
	}
	else{
		if((n+1)%4==0){
			cout<<0<<endl;
			cout<<(n+1)/4*2<<" ";
			for(int i=1;i<=(n+1)/4;i++){
				if((n+1)/4==i){
					cout<<i<<" "<<(n+1)/2<<" ";
				}
				else{
					cout<<i<<" "<<n-i+1<<" ";
				}
			}
			cout<<endl;
		}
		else{
			cout<<1<<endl;
			cout<<(n+1)/4*2<<" ";
			for(int i=1;i<=(n+1)/4;i++){
				if((n+1)/4==i){
					cout<<(n+1)/2<<" "<<n-i+1<<" ";
				}
				else{
					cout<<i<<" "<<n-i+1<<" ";
				}
			} 
			cout<<endl;
		}
	}
	return 0;
}


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值