直接贪心的做法是不对的(例如: 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个,这些对都可以凑成一样的大小
剩下的为粉红色的部分, 这些数字有(n-(2*m-1))%(2*m)+(2*m-1)个 (如样例 1~10),然后对这部分进行从大到小的贪心.....(感觉还是有问题???....)
n=100,m=5的数据
100 5
YES
20 10 1 11 100 12 99 13 98 14 97 15 96 16 95 17 94 18 93 19 92
20 9 2 20 91 21 90 22 89 23 88 24 87 25 86 26 85 27 84 28 83
20 8 3 29 82 30 81 31 80 32 79 33 78 34 77 35 76 36 75 37 74
20 7 4 38 73 39 72 40 71 41 70 42 69 43 68 44 67 45 66 46 65
20 6 5 47 64 48 63 49 62 50 61 51 60 52 59 53 58 54 57 55 56
参考题解: http://blog.csdn.net/queuelovestack/article/details/47321211
4 1 2 5 3 5 2 9 3
NO YES 1 5 2 1 4 2 2 3 NO YES 3 1 5 9 3 2 6 7 3 3 4 8
/* *********************************************** Author :CKboss Created Time :2015年08月07日 星期五 14时23分36秒 File Name :HDOJ5355_2.cpp ************************************************ */ #include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #include <string> #include <cmath> #include <cstdlib> #include <vector> #include <queue> #include <set> #include <map> using namespace std; typedef long long int LL; LL n,m; vector<int> vi[10]; set<int> v; void init() { for(int i=0;i<10;i++) vi[i].clear(); } int main() { //freopen("in.txt","r",stdin); //freopen("out.txt","w",stdout); int T_T; scanf("%d",&T_T); while(T_T--) { cin>>n>>m; init(); LL sum=n*(n+1)/2; if(sum%m||n+1<2*m) { puts("NO"); continue; } LL c=(n-m*2+1)%(m*2)+m*2-1; v.clear(); for(int i=1;i<=c;i++) { v.insert(i); } LL s=c*(c+1)/(m*2); for(int i=0;i<m;i++) { set<int>::iterator it; LL ts=0; while(ts<s) { it=v.upper_bound(s-ts); LL tmp=*--it; vi[i].push_back(tmp); ts+=tmp; v.erase(it); } } int st=c+1; int ed=n; int k=(n-c)/(2*m); for(int i=0;i<m;i++) { for(int j=0;j<k;j++) { vi[i].push_back(st); st++; vi[i].push_back(ed); ed--; } } puts("YES"); for(int i=0;i<m;i++) { int sz=vi[i].size(); printf("%d",sz); for(int j=0;j<sz;j++) { printf(" %d",vi[i][j]); } putchar(10); } } return 0; }
标程的代码:
#include <bits/stdc++.h> using namespace std; typedef long long ll; int sol(){ int n,m; scanf("%d%d",&n,&m); if(((n+1ll)*n>>1)%m!=0 || m * 2 -1 > n) return puts("NO"); const int c=(n+1-m*2)%(m*2)+m*2-1, s=c*(c+1)/(m*2), d=(n-c)/(m*2); puts("YES"); set<int> v; for(int i=1;i<=c;++i)v.insert(i); for(int j=0,l=c+1;j<m;++j,putchar('\n')){ static int o[32],c,r; for(c=r=0;r<s;){ auto it = v.upper_bound(s-r); r+=o[c++]=*--it; v.erase(it); } printf("%d",c+d*2); for(int i=0;i<c;++i)printf(" %d",o[i]); for(int i=0;i<d;++i)printf(" %d %d",l++,n--); } } int main(){ int T; for(scanf("%d",&T);T--;sol()); }