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.
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.
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.
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 }