hdu5355--Cake(构造)

来源:互联网 发布:mac 最近使用字体 编辑:程序博客网 时间:2024/05/23 14:29

题目链接:点击打开链接

题目大意:给出n块蛋糕,现在有m个人要分蛋糕,要求分的大小是一样的,并且蛋糕不能切开,问能不能分成,并输出可以分成的方法。

计算蛋糕的和sum,如果sum不能整除m,或者sum/m<n,将式子转化,得n < 2*m-1 那一定是不可以的。

同样也就得到n >= 2*m-1,就是可以的,所以可以先计算出(n-2*m+1)%(2*m)+2*m-1,先拿出2*m-1个来,那么剩下的蛋糕中,每连续2*m个都可以组成一个相同的数值(小的递增,大的递减),最终会剩下mod = (n-2*m+1)%(2*m)+2*m-1个蛋糕,可以认为这些蛋糕是从1到mod,计算剩余的和sum,和平均数ave,现在我们要做的就是把1到mod分为m份,使用set,不断组成ave,一直到分为m份。

#include <cstdio>#include <cstring>#include <vector>#include <set>#include <algorithm>using namespace std ;#define LL __int64vector<int> vec[11] ;set<int> s ;set<int>::iterator iter ;int n , m ;int main() {    LL sum ;    int t , n , m , num , mod ;    int i , j , k ;    scanf("%d", &t) ;    while( t-- ) {        scanf("%d %d", &n, &m) ;        sum = n ;        sum = sum*(sum+1)/2 ;        if( sum%m || n < 2*m-1) {            printf("NO\n") ;            continue ;        }        mod = (n-2*m+1)%(2*m) + 2*m-1 ;        num = (n-mod)/(2*m) ;        for(i = 1 ; i <= m ; i++) vec[i].clear() ;        i = mod+1 ; j = n ;        while( num-- ) {            i = mod+1+(2*m)*num ;            j = i+(2*m)-1 ;            for(k = 1 ; k <= m ; k++) {                vec[k].push_back(i) ;                vec[k].push_back(j) ;                i++ ; j-- ;            }        }        sum = mod ;        sum = sum*(sum+1)/2 ;        sum /= m ;        s.clear() ;        for(i = 1 ; i <= mod ; i++)            s.insert(i) ;        for(i = 1 ; i <= m ; i++) {            k = sum ;            while( k ) {                iter = s.upper_bound(k) ;                iter-- ;                //printf("%d\n", *iter) ;                vec[i].push_back(*iter) ;                k -= *iter ;                s.erase(*iter) ;            }        }        printf("YES\n") ;        for(i = 1 ; i <= m ; i++) {            num = vec[i].size() ;            printf("%d ", num) ;            for(j = 0 ; j < num-1 ; j++)                printf("%d ", vec[i][j]) ;            printf("%d\n", vec[i][j]) ;        }    }    return 0 ;}



0 0
原创粉丝点击