cf1619F 构造/2000
F - Let's Play the Hat?
题意: n个人m张桌子玩k次游戏。每个人必须玩k次游戏。每个桌子的人数都是 n/m (上取整 或 下取整)。
定义 为第 个人在人数为 n/m(上取整) 的桌子上玩的游戏次数。对任意 $ i, j $ 满足
Solution: 首先,m张桌子分给n个人,显然每张桌子的人数是确定的——
大桌为n%m个,小桌为 m - n%m个。(每张桌子先坐 n/m(下取整)个人,剩下的 n%m 个人随便挑一个坐)
我们要使每个人在大桌上坐的次数相差不超过1。策略是这样的:
每次让坐在大桌上次数较少的人坐大桌,坐不满从较多的人补。这样显然可以保证相差不超过1。
实现的话可以考虑利用vector的rotate来滚动选择的人,每次坐大桌的人都让其移动到整个序列的最后排队。
#include <bits/stdc++.h>
using namespace std;
inline void read(int &a) {a=0;int c=getchar(),b=1; while(c>'9'||c<'0') {if(c=='-')b=-1;c=getchar();} while(c>='0'&&c<='9') a=(a<<3)+(a<<1)+c-48,c=getchar();a*=b; }
const int N = 2e5 + 5;
int t, n, m, k;
int main()
{
read(t);
while(t--)
{
read(n); read(m); read(k);
vector<int>v(n);
for(int i = 0; i < n; i++) v[i] = i + 1;
int bt = n % m, bn = ceil(1.0 * n / m), sn = n / m;
for(int i = 1; i <= k; i++)
{
int pos = 0;
for(int j = 1, num; j <= m; j++)
{
if(j <= bt) num = bn; else num = sn;
cout << num << ' ';
while(num--) cout << v[pos++] << ' ';
puts("");
}
rotate(v.begin(), v.begin() + bn * bt, v.end());
}
puts("");
}
return 0;
}