1. 程式人生 > >codeforces519C Cram Time

codeforces519C Cram Time

In a galaxy far, far away Lesha the student has just got to know that he has an exam in two days. As always, he hasn’t attended any single class during the previous year, so he decided to spend the remaining time wisely.

Lesha knows that today he can study for at most a hours, and he will have b hours to study tomorrow. Note that it is possible that on his planet there are more hours in a day than on Earth. Lesha knows that the quality of his knowledge will only depend on the number of lecture notes he will read. He has access to an infinite number of notes that are enumerated with positive integers, but he knows that he can read the first note in one hour, the second note in two hours and so on. In other words, Lesha can read the note with number k in k hours. Lesha can read the notes in arbitrary order, however, he can’t start reading a note in the first day and finish its reading in the second day.

Thus, the student has to fully read several lecture notes today, spending at most a hours in total, and fully read several lecture notes tomorrow, spending at most b hours in total. What is the maximum number of notes Lesha can read in the remaining time? Which notes should he read in the first day, and which — in the second?

Input

The only line of input contains two integers a and b (0≤a,b≤109) — the number of hours Lesha has today and the number of hours Lesha has tomorrow.

Output

In the first line print a single integer n (0≤n≤a) — the number of lecture notes Lesha has to read in the first day. In the second line print n distinct integers p1,p2,…,pn (1≤pi≤a), the sum of all pi should not exceed a

.

In the third line print a single integer m(0≤m≤b) — the number of lecture notes Lesha has to read in the second day. In the fourth line print m distinct integers q1,q2,…,qm (1≤qi≤b), the sum of all qi should not exceed b

. All integers pi and qi should be distinct. The sum n+m should be largest possible.

在給定的時間中讀儘可能多的紙條,第 i 個紙條需要 i 個單位時間。 現在考慮對紙條的選取。現記在這兩天中能看過最多的紙條數為 x=n+m。那麼考慮對任意可行長度為 x 的序列,如果在序列中存在一個編號大於 x 的紙條,那麼在區間[1,x]內必然存在一個數 n ,使得 n 不在當前得序列中。那麼,將這個大於 x 的紙條用 n 替換,由於替換後總耗時一定小於替換前的耗時,因而替換後的序列也是一個可行序列。重複這樣的替換,直到不存在一個紙條的編號大於 x 。由此可知,必然會存在一個解,在這個解中任意的紙條編號都小於 x 。由於存在總時間的限制,故可以得到如下不等關係:

[x*(x+1)]/2<=a+b

根據這個不等關係解出 x 的值。其中 x 的最大值可由題目中資料的最大規模得出。 因為 a<=a+b ,故在區間[1,x]中必定存在一個序列,使得序列中所有元素的和等於 a 。所以,設計DFS演算法,在區間[1,x]中找出這個序列,作為第一天的序列。根據之前所述,在區間[1,x]中剩餘的元素就為第二天的序列。

#include <stdio.h>
#include <math.h>
#include <cstring>
#include <climits>
#include <algorithm>
using namespace std;

long long a,b;
long peak,len;
bool used[100240];
int first[100240];
bool seek(int star,int res,int dep);
int main(){
    scanf("%d %d",&a,&b);
    peak=((sqrt(1+8*(a+b))-1)/2);
    if(b==0){
        printf("%d\n",peak);
        for(int i=1;i<=peak;i++)
            printf("%d ",i);
        printf("\n0\n\n");
        return 0;
    }
    for(int i=0;i<=peak+10;i++)
        used[i]=false,first[i]=-1;
    len=0;
    if(a!=0){
        seek(peak,a,0);
        for(int i=0;first[i]!=-1;i++)
            len++;
        printf("%d\n",len);
        for(int i=0;i<len;i++)
            printf("%d ",first[i]);
        printf("\n");
    }else{
        printf("0\n\n");
    }
    printf("%d\n",peak-len);
    for(int i=1;i<=peak;i++)
        if(!used[i])
            printf("%d ",i);
    printf("\n");
    return 0;
}
bool seek(int star,int res,int dep){
    if(res==0)
        return true;
    bool sym=false;
    for(int i=star;i>0;i--){
        if(!used[i]){
            int num=res-i;
            if(num<0)
                continue;
            used[i]=true;
            first[dep]=i;
            if(seek(i-1,num,dep+1)){
                sym=true;
                break;
            }
            used[i]=false;
        }
    }
    return sym;
}

注意特判,即輸入為0時。