CodeForces

来源:互联网 发布:葫芦侠数据不存在 编辑:程序博客网 时间:2024/06/14 18:25

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;}


原创粉丝点击