标签:
题目链接:点击打开链接
题目大意:给出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 __int64 vector<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 ; }
版权声明:本文为博主原创文章,未经博主允许不得转载。
标签:
原文地址:http://blog.csdn.net/winddreams/article/details/47393873