题意:就是给你一个n,k,k满足一个性质为n的约数,现在给你一个n一个k问你是否能把这n个数分成k组,每组n/k个,每组的权值相等。
解法:我们仔细观察就会发现这n个数是一个等差数列我们简单的求一下和判断一下这个和是否能整除于k即可,若不能整除与k则输出no即可,之后n为偶数的情况时候我们直接一个蛇形构造即可完成对其 的构造,当n为奇数时我们就要构造出前3列后面的列数为偶数根据n为偶数的情况来进行一样的构造即可,这题的难点就在于构造前3列,例如n等于15 k等于3 我们可以将其构造前列,第一列我们直接从1开始到k 第二列我们从(k+1)/2这个位置开始构造到k这个位置之后在从第二列的第一个位置开始构造到k/2这个位置,第3列的话我们可以通过求出前3列的和再除上k求出每一组的总和sum,之后用sum减去每一组前两个数的值即可。剩下的列数直接根据n为偶数那样构造即可.
代码
#include<bits/stdc++.h>
using namespace std;
const int N=1e6+10;
vector<int>v[N];
int main()
{
// freopen("1.txt","r",stdin);
// freopen("1.out","w",stdout);
int t;
scanf("%d",&t);
while(t--)
{
long long n,k; scanf("%lld%lld",&n,&k);
for(int i=1;i<=k;i++) v[i].clear();
// int t=n/k;
long long sum=n*(n+1)/2;
if(sum%k) {puts("no");continue;}
else if(k==1)
{
for(int i=1;i<=n;i++)
v[1].push_back(i);
}else if(n&1)
{
long long num=1;
long long sm=k*3*(k*3+1)/2;
sm/=k;
for(int i=1;i<=k;i++)
v[i].push_back(num++);
for(int i=(k+1)/2;i<=k;i++) v[i].push_back(num++);
for(int i=1;i<(k+1)/2;i++)v[i].push_back(num++);
for(int i=1;i<=k;i++)
{
int tt=sm-v[i][0]-v[i][1];
v[i].push_back(tt);
num++;
}
int tm=1;
while(1)
{
if(num>=n)break;
if(tm&1)
{
for(int i=1;i<=k;i++)
v[i].push_back(num++);
}else
{
for(int i=k;i>=1;i--)
v[i].push_back(num++);
}
tm++;
}
}else
{ // puts("bug");
long long num=1;long long tt=1;
while(1)
{
if(num>=n)break;
if(tt&1)
{ for(int i=1;i<=k;i++)
v[i].push_back(num++);
}else
{
for(int i=k;i>=1;i--)
v[i].push_back(num++);
}
tt++;
}
}
puts("yes");
for(int i=1;i<=k;i++)
{ for(int j=0;j<n/k;j++)
if(j!=n/k-1)
cout<<v[i][j]<<" ";
else cout<<v[i][j]<<endl;
}
}
}