2019 Multi-University Training Contest 4.Divide the Stones(贪心)

时间:2023-01-03 15:19:16

题意:给你n和k (k|n) 有n个数 第i个数权值为i 要你求权值相同且分成k组 且每组的个数为n/k

思路:恶心构造题,首先对于总权值不能分为k份的 显然不能分成 然后 我们把n/k 分奇偶 我们可以发现 偶数我们可以每k个当成一组

对于奇数 我们可以先处理前3*k 然后同样处理剩下的数

 

#include <bits/stdc++.h>
#define ls(x) T[x].ch[0]
#define rs(x) T[x].ch[1]
#define fa(x) T[x].fa
#define root  T[0].ch[1]
using namespace std;
const int N = 1e5+7;
const int inf = 0x3f3f3f3f;
typedef long long ll;
const ll mod = 1e9+7;
int vis[N];
vector<ll> v[N];
ll te[N];
int main(){
    //ios::sync_with_stdio(false);
    //cin.tie(0); cout.tie(0);
    int t; scanf("%d",&t);
    while(t--){
        ll n,k; scanf("%lld%lld",&n,&k);
        for(int i=0;i<k;i++) v[i].clear();
        memset(te,0,sizeof(te));
        ll x=(n*(n+1))/2; bool f=1;
        if(n==1&&k==1){
            printf("yes\n");
            printf("1\n");
            continue;
        }
        if(x%k!=0) f=0;
        if(f&&n>(x/k)) f=0;
        if(f){
            if((n/k)%2==0){
                for(ll i=1;i<=n/2;i++){
                    v[i%k].push_back(i);
                    v[i%k].push_back(n-i+1);
                }
                printf("yes\n");
                for(int i=0;i<=k-1;i++){
                    for(int j=0;j<v[i].size();j++)
                        if(j==0) printf("%lld",v[i][j]);
                        else printf(" %lld",v[i][j]);
                    printf("\n");
                }
            }else{
                if(k&1){
                    for(ll i=1;i<=k;i++){
                        v[i%k].push_back(i);
                        te[i%k]+=i;
                    }
                    for(ll i=1;i<=k;i++){
                        v[(i-k/2+k)%k].push_back(i+k);
                        te[(i-k/2+k)%k]+=(i+k);
                    }
                    for(ll i=1;i<=k;i++){
                        v[i%k].push_back((1+3*k)*3/2-te[i%k]);
                    }
                    for(ll i=1;i<=(n-3*k)/2;i++){
                        v[i%k].push_back(i+3*k);
                        v[i%k].push_back(n-i+1);
                    }
                    printf("yes\n");
                    for(int i=0;i<=k-1;i++){
                        for(int j=0;j<v[i].size();j++)
                            if(j==0) printf("%lld",v[i][j]);
                            else printf(" %lld",v[i][j]);
                        printf("\n");
                    }
                }else{
                    printf("no\n");
                }
            }
        }else{
            printf("no\n");
        }
    }
    return 0;
}