传送门:http://acm.hdu.edu.cn/showproblem.php?pid=6616
首先讨论n,n/k的奇偶性问题
1.n是偶数,n/k是偶数
此时每堆的重量为 n*(n+1)/2/k ,则有n/k%2==0 那么为 t*(n+1),所以此时直接1+n 2+(n-1)这样配对就行了
2.n是偶数,n/k是奇数
可以得出k一定是偶数,此时每堆重量为n*(n+1)/2/k,n/k为奇数,而(n+1)又为奇数,%2=1,所以无解
3.n是奇数,由于k是n因子,所以k和n/k都为奇数
llg告诉我一个很巧妙的构造方法,我们当场也没有想出来的
考虑n=k/2,我们k个数k个数字地一行一行放进k堆中。
那么首先k堆中先按顺序放上 -n -n+1 ....-1 0 1 2 .... n-1 n (相对大小 )
我们每次都向k堆上加上一个排列,只要得到的相对结果还是-n到n,且没有重复的话,那么最后一行就一定能补出一个结果,使得相对大小为0。
考虑 -4 -3 -2 -1 0 1 2 3 4
我们再下一行放上 0 1 2 3 4 -4 -3 -2 -1
这样就会得到-4 -2 0 2 4 -3 -1 1 3这样的结果
那么下下一行依然这样对应着放数就行了
注意特判,n/k==1 且 n==1的情况是可以的,n>1的情况是不行的,WA了好久
题解好像是说吧前3行拉出来,可以构成相等的k堆,剩下的没堆就只剩偶数了,直接均分着放,像情况1一样
学弟给出一个想法,虽然他们没写完。对l=min(k,n/k)做一个l*l的幻方,幻方必须是奇数的长度,可以保证每行每列和都相等,然后剩下的就是偶数长度了,也是直接像情况1一样均分着放。
#include<bits/stdc++.h>
#define maxl 100010
using namespace std;
long long k,n,sum,t;
long long dy[maxl];
long long last[maxl],to[maxl];
long long tmp[maxl];
bool flag;
vector <long long> ans[maxl];
inline void prework()
{
scanf("%lld%lld",&n,&k);
sum=1ll*n*(n+1)/2;
for(long long i=1;i<=k;i++)
ans[i].clear();
}
inline void mainwork()
{
flag=false;
if(sum%k!=0)
return;
sum=sum/k;
long long id;
t=n/k;
if(t%2==0)
{
long long id=1;
for(long long i=1;i<=k;i++)
{
for(long long j=1;j<=t/2;j++)
{
ans[i].push_back(id);
ans[i].push_back(n-id+1);
id++;
}
}
flag=true;
}
else
{
if(n/k==1)
{
if(n==1)
{
ans[1].push_back(1);
flag=true;
}
return;
}
for(long long i=1;i<=k/2+1;i++)
{
dy[i]=k/2+i;
to[i]=(i-1)*2+1;
}
for(long long i=k/2+2;i<=k;i++)
{
dy[i]=i-(k/2)-1;
to[i]=(i-(k/2)-1)*2;
}
for(long long i=1;i<=k;i++)
ans[i].push_back(i),last[i]=i,tmp[i]=i;
long long num;
for(long long i=2;i<n/k;i++)
{
for(long long j=1;j<=k;j++)
{
num=dy[last[j]]+(i-1)*k;
ans[j].push_back(num);
last[j]=to[last[j]];
tmp[j]+=num;
}
}
for(long long i=1;i<=k;i++)
ans[i].push_back(sum-tmp[i]);
flag=true;
}
}
inline void print()
{
if(flag)
{
puts("yes");
long long l;
for(long long i=1;i<=k;i++)
{
for(long long j=0;j<n/k;j++)
printf("%lld%c",ans[i][j],(j==(n/k-1))?'\n':' ');
}
}
else
puts("no");
}
int main()
{
long long t;
scanf("%lld",&t);
for(long long i=1;i<=t;i++)
{
prework();
mainwork();
print();
}
return 0;
}