[2019杭电多校第四场][hdu6616]Divide the Stones
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6616
题意是说n个数分别为1-n,将n个数分成k堆,能否满足每堆个数相等,数值之和相等。保证n%k=0。
构造题神马的太烦了略略略
我的构造方式是这样的,先判断每堆的个数,然后分奇偶讨论一下
每堆个数为偶时:
可以将n个数分成n/2对,如n为12时,分成1-12,2-11,3-10,4-9,5-8,6-7这样。
然后根据每堆的个数将n/2对分别放入每堆中。
如n=12,k=3时:
第一堆为1-12,2-11。
第二堆为3-10,4-9。
第三堆为5-8,6-7。
这样很好想。
每堆个数为奇时:
先用蛇型方式构造出k堆的前m-2项(m为每堆的个数)
如n=15,k=3时:
1 6 7 X X
2 5 8 X X
3 4 9 X X
三堆分别如上。
然后发现每堆现在的和为14 15 16单调递增。所以我们用剩余元素构造出一个单调递减的序列即可。
剩余元素为10 11 12 13 14 15,我们用15-11,13-12,14-10,构造出一个递减序列即可。
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<string> 5 #include<algorithm> 6 using namespace std; 7 typedef long long ll; 8 const int maxn = 1e5 + 10; 9 int main() { 10 int t; 11 scanf("%d", &t); 12 while (t--) { 13 ll n, m, k; 14 scanf("%lld%lld", &n, &k); 15 m = n / k; 16 ll sum = n * (n + 1) / 2; 17 if (k == 1) { 18 printf("yes\n"); 19 for (int i = 1; i <= n; i++) 20 printf("%d%c", i, i == n ? '\n' : ' '); 21 } 22 else if (sum%k) { 23 printf("no\n"); 24 continue; 25 } 26 else { 27 if (m & 1) { 28 int num = 0; 29 int tot = sum / k; 30 int tmp = n; 31 printf("yes\n"); 32 for (int i = 1; i <= k; i++) { 33 for (int j = 1; j <= m - 2; j++) { 34 int x; 35 if (j & 1) 36 printf("%d ", x = (j - 1)*k + i); 37 else 38 printf("%d ", x = j * k - i + 1); 39 if (i == 1) 40 tot -= x; 41 } 42 printf("%d %d\n", tmp, tot - tmp); 43 tot--; 44 tmp -= 2; 45 if (tmp < n - k)tmp = n - 1; 46 } 47 } 48 else { 49 int cnt = 0; 50 printf("yes\n"); 51 for (int i = 1; i <= n / 2; i++) { 52 cnt += 2; 53 printf("%d %d", i, n - i + 1); 54 if (cnt == m) { 55 printf("\n"); 56 cnt = 0; 57 } 58 else 59 printf(" "); 60 } 61 } 62 } 63 } 64 }