hdu5355 Cake(构造)

转载请注明出处: http://www.cnblogs.com/fraud/          ——by fraud

Cake

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others)
Total Submission(s): 1517    Accepted Submission(s): 233
Special Judge

Problem Description

There are m soda and today is their birthday. The 1-st soda has prepared n cakes with size 1,2,…,n. Now 1-st soda wants to divide the cakes into m parts so that the total size of each part is equal.

Note that you cannot divide a whole cake into small pieces that is each cake must be complete in the m parts. Each cake must belong to exact one of m parts.

Input

There are multiple test cases. The first line of input contains an integer T, indicating the number of test cases. For each test case:

The first contains two integers n and m (1≤n≤105,2≤m≤10), the number of cakes and the number of soda.
It is guaranteed that the total number of soda in the input doesn’t exceed 1000000. The number of test cases in the input doesn’t exceed 1000.

Output

For each test case, output "YES" (without the quotes) if it is possible, otherwise output "NO" in the first line.

If it is possible, then output m lines denoting the m parts. The first number si of i-th line is the number of cakes in i-th part. Then si numbers follow denoting the size of cakes in i-th part. If there are multiple solutions, print any of them.

Sample Input

4

1 2

5 3

5 2

9 3

Sample Output

NO

YES

1 5

2 1 4

2 2 3

NO

YES

3 1 5 9

3 2 6 7

3 3 4 8

其实这题还是不容易过的,比赛的时候一看居然都过了100人了,而且发现直接贪心是不对的,于是乎乱搞了一发。。。结果居然过了。。。

这题首先只有在不能整除以及n<2m-1的时候才是NO,其余情况都是YES

然后在[2m-1,4m-2]的范围内贪心,然后之后,每2m个相互构一组

  1 /**
  2  * code generated by JHelper
  3  * More info: https://github.com/AlexeyDmitriev/JHelper
  4  * @author xyiyy @https://github.com/xyiyy
  5  */
  6
  7 #include <iostream>
  8 #include <fstream>
  9
 10 //#####################
 11 //Author:fraud
 12 //Blog: http://www.cnblogs.com/fraud/
 13 //#####################
 14 //#pragma comment(linker, "/STACK:102400000,102400000")
 15 #include <iostream>
 16 #include <sstream>
 17 #include <ios>
 18 #include <iomanip>
 19 #include <functional>
 20 #include <algorithm>
 21 #include <vector>
 22 #include <string>
 23 #include <list>
 24 #include <queue>
 25 #include <deque>
 26 #include <stack>
 27 #include <set>
 28 #include <map>
 29 #include <cstdio>
 30 #include <cstdlib>
 31 #include <cmath>
 32 #include <cstring>
 33 #include <climits>
 34 #include <cctype>
 35
 36 using namespace std;
 37 #define pb(X) push_back(X)
 38 #define rep(X, N) for(int X=0;X<N;X++)
 39 #define rep2(X, L, R) for(int X=L;X<=R;X++)
 40 typedef long long ll;
 41
 42 #define gao() out<<"NO"<<endl
 43 vector<int> ans[11];
 44 int used[50];
 45 ll tot;
 46
 47 class hdu5355 {
 48 public:
 49     int ave;
 50
 51     void solve(std::istream &in, std::ostream &out) {
 52         int n, m;
 53         in >> n >> m;
 54         tot = (ll) (n + 1) * n / 2;
 55         if (tot % m != 0) {
 56             gao();
 57             return;
 58         }
 59         int tmp = tot / m;
 60         if (n < 2 * m - 1) {
 61             gao();
 62             return;
 63         }
 64         int num = n / m;
 65         if (tmp == n) {
 66             out << "YES" << endl;
 67             out << 1 << " " << n << endl;
 68             rep(i, m - 1) {
 69                 out << 2 << " " << i + 1 << " " << n - i - 1 << endl;
 70             }
 71             return;
 72         }
 73         if (m == 1) {
 74             out << "YES" << endl;
 75             out << n;
 76             rep2(i, 1, n)out << " " << i;
 77             out << endl;
 78             return;
 79         }
 80         rep2(i, 1, m)ans[i].clear();
 81         int f = n;
 82         int c = 1;
 83         /*while(n>=4*m-1){
 84             rep2(i,1,m){
 85                 if(c&1) ans[i].pb(f - i + 1);
 86                 else ans[i].pb(f - m + i);
 87             }
 88             f -= m;
 89             n -= m;
 90             c++;
 91             rep2(i,1,m){
 92                 if(c&1) ans[i].pb(f - i + 1);
 93                 else ans[i].pb(f - m + i);
 94             }
 95             f -= m;
 96             n -= m;
 97             c++;
 98         }*/
 99         c = (n + 1 - m * 2) % (m * 2) + m * 2 - 1;
100         int d = (n - c) / (2 * m);
101         for (int i = 1, j = c + 1; i <= m; i++) {
102             rep(k, d)ans[i].pb(j++), ans[i].pb(n--);
103         }
104         tot = n;
105         n = c;
106         ave = (ll) (1 + n) * n / 2 / m;
107         set<int> s;
108         rep2(i, 1, n)s.insert(i);
109         rep2(i, 1, m) {
110             rep(j, ave) {
111                 auto it = s.upper_bound(ave - j);
112                 ans[i].pb(*--it);
113                 j += *it;
114                 s.erase(it);
115                 j--;
116             }
117         }
118
119
120         // clr(used,0);
121         // rep(i,tot)a[i] = n - i;
122         // if(dfs(0,0,n,1)){
123         //if(dfs(m,n,0,0,n)){
124         out << "YES" << endl;
125         // rep2(i,1,n)ans[used[i]].pb(i);
126         rep2(i, 1, m) {
127             int sz = ans[i].size();
128             out << sz;
129             rep(j, sz) {
130                 out << " " << ans[i][j];
131             }
132             out << endl;
133         }
134         //}else out<<"NO"<<endl;
135         /*if(n % m != 0){
136             gao();
137             return;
138         }
139         if(num&1){
140             if(m&1){
141                 out<<"YES"<<endl;
142                 run(m);
143                 rep2(i,1,m){
144                     out<<num;
145                     rep(j,ans[i].size()){
146                         out<<" "<<ans[i][j];
147                     }
148                     int last = 3 * m + i;
149                     int f = 4 * m;
150                     rep2(j,4,num){
151                         out<<" "<<last;
152                         f += m;
153                         if(j&1)last = f- m + i;
154                         else last = f - i + 1;
155                     }
156                     out<<endl;
157                 }
158
159             }else{
160                 gao();
161                 return;
162             }
163         }else{
164             out<<"YES"<<endl;
165             rep2(i,1,m){
166                 out<<num;
167                 int last = i;
168                 int f = m;
169                 rep(j,num){
170                     out<<" "<<last;
171                     f += m;
172                     if(j&1)last = f-i+1;
173                     else last = f - m + i;
174                 }
175             }
176         }*/
177
178     }
179
180     bool dfs(int num, int now, int u, int m) {
181         if (now == 0) {
182             int i = tot;
183             while (used[i])i--;
184             used[i] = m;
185             if (dfs(num + 1, i, i - 1, m))return 1;
186             used[i] = 0;
187             return 0;
188         }
189         if (now == ave) {
190             if (num == tot)return 1;
191             else return dfs(num, 0, tot, m + 1);
192         }
193         for (int i = u; i > 0; i--) {
194             if (!used[i] && now + i <= ave) {
195                 used[i] = m;
196                 if (dfs(num + 1, now + i, i - 1, m))return 1;
197                 used[i] = 0;
198             }
199         }
200         return false;
201     }
202
203     bool dfs(int m, int n, int tot, int num, int now) {
204         if (!m) {
205             return 1;
206         }
207         if (tot = ave) {
208             if (dfs(m - 1, n, 0, num, 0))return 1;
209         }
210         if (tot == 0) {
211             int i = n;
212             while (used[i])i--;
213             used[i] = m;
214             if (dfs(m, n, tot + i, num + 1, i))return 1;
215             used[i] = 0;
216             return 0;
217         }
218         for (int i = now; i > 0; i--) {
219             if (!used[i] && tot + i <= ave) {
220                 used[i] = m;
221                 if (dfs(m, n, tot + i, num + 1, i - 1))return 1;
222                 used[i] = 0;
223             }
224         }
225         return false;
226     }
227
228 };
229
230 int main() {
231     std::ios::sync_with_stdio(false);
232     std::cin.tie(0);
233     hdu5355 solver;
234     std::istream &in(std::cin);
235     std::ostream &out(std::cout);
236     int n;
237     in >> n;
238     for (int i = 0; i < n; ++i) {
239         solver.solve(in, out);
240     }
241
242     return 0;
243 }
时间: 2024-10-16 11:43:42

hdu5355 Cake(构造)的相关文章

hdu5355 Cake

Problem Description There are m soda and today is their birthday. The 1-st soda has prepared n cakes with size 1,2,-,n. Now 1-st soda wants to divide the cakes into m parts so that the total size of each part is equal. Note that you cannot divide a w

hdu 5535 Cake 构造+记忆化搜索

链接:http://acm.hdu.edu.cn/showproblem.php?pid=5355 题意:给定n与m,其中1<= n <= 1e5,2 <= m <= 10;问是否存在将1~n个数分成m组,使得每组的和相等:若存在输出m行,每行表示一组的值,否则输出NO; ps:总共T<=1000组数据,还是挺大的: 思路:预判之后,若可能存在则直接以2m为周期,从大往小构造出和相等的m组,这样就可以将n的值缩小到2m~4m-2:因为当n = 4m-1时,再次减去一个周期,下

HDOJ5355 Cake 构造

直接贪心的做法是不对的(例如: 23 6 , 27 7 , 28 7, 31 8 等...) 多校的时候因为SPJ的问题很多WA的程序都过了,实际上这题并没有那么水...... 无解的有两种情况 1: sum不能被m整除 2: sum/m比n小 剩下的情况都有解: 标程的做法是根据: n(n+1)/(2*m) 每一组里都有k对组合,如第一行中的(11 100) (12 99) (13 98).... 因为有m行所以这样的组合有2*k*m个,这些对都可以凑成一样的大小 剩下的为粉红色的部分, 这些

递归练习1

感觉自己这方面很弱,都是看着题解做的orz.. fzu2038 Another Postman Problem(递归求解) 题意:n个点n-1条边组成无向连通图,求每个点到其他所有点的路径总和的和. 题解:每条边的访问次数为边两端点数乘积的两倍.递归遍历每个点的每条边即可. 1 #include<cstdio> 2 #include<vector> 3 #include<cstring> 4 using namespace std; 5 const int N=1e5+

HDU 5355 Cake (WA后AC代码,具体解析,构造题)

题目链接:http://acm.hdu.edu.cn/showproblem.php? pid=5355 题面: Cake Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others) Total Submission(s): 1632    Accepted Submission(s): 273 Special Judge Problem Description There are s

HDU 5355 Cake (WA后AC代码,详细解析,构造题)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5355 题面: Cake Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others) Total Submission(s): 1632    Accepted Submission(s): 273 Special Judge Problem Description There are m

hdu 5355 Cake(构造+回溯)

题意: 给出一个蛋糕,切成1~n大小的n块,问能否在不继续切割的情况下拼凑出m等份. 解析: 首先可以求出这些蛋糕的总和n?(n+1)/2,如果总和sum%m != 0那么就不肯能被平分成m份,那么输出"NO". 接下来计算平均数avg=sum/m,如果平均数avg < n的话,蛋糕是不可能用完的,同样也输出"NO". 剩下的情况蛋糕是一定能拼成"YES"的,那么可以将这些蛋糕以2*m为单位一组一组的分配,每个人拿当前这组的最大和最小,次大

Java的结构之美【1】——构造对象

当我们遇到多个构造器参数的时候可能会想到用构件器,代码如下: /** * 构建器 * @author 阳光小强 * */ public class Lunch { private String cake; private String meat; private String milk; private String drink; public Lunch(){ this(null); } public Lunch(String meat){ this(null, meat, null); }

poj 2515 Birthday Cake

1 /** 2 大意 : 求1^m + 2^m + 3^m + 4^m +....+ n^m 3 解题步骤: 4 先构造从0到m的第1阶差分序列,然后以下所有2---->p阶的差分表. 5 令C[n+1][1]=n,用递推构造C[n+1][1]~C[n+1][p+1]的组合数打个一维表: 6 最后利用C0*C[1]+C1*C[2]+...+Cp*C[p+1]得出答案... 7 注意: java 提交时,一定要将包名去掉,,并且类名为Main 8 这一题就是因为多加了个包名,,一直是 runtim