题目链接:点击打开链接
题目大意:给出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