首先討論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;
}