(多校)子集 (subset)


第一次考場切構造題

首先我們摸一下樣例

有一個顯然的結論

如果我們依次從左到右把 \(n\) 個數分成 \(\frac{n}{k}\)

並且每一份大小都為 \(k\)

那么每一個子集在每一組數中都恰好選一個

\[1.2.3 : 4.5.6 : 7.8.9 : 10.11.12 \]

所以,我們不妨把序列表示成:

\[1.2.3 : 1.2.3 : 1.2.3 : 1.2.3 \]

轉換成矩陣:

\[1-1-1-1 \]

\[2-2-2-2 \]

\[3-3-3-3 \]

那么題意就轉換成讓每一列上的數互換,求一種方案使得每一行的數字之和相等

樣例這種情況很好想,我么只要把 \(\frac{n}{2k}\) 列的數字 \(reverse\) 一下就好了

這種情況其實是針對 \(n/k\) 為偶數的情況的

考慮 \(n/k\) 為奇數的情況

容易發現我們只需要大力手玩一下前三列的數字,使其每一行的數字和相等

對於剩下的 \(n/k-3\) 列的數字按 \(n/k\) 為偶數的情況做就好了

Code
#include <bits/stdc++.h>
#define re register
#define int long long
// #define lls long long
#define pir make_pair
#define fr first 
#define sc second
#define db long double
using namespace std;
const int mol=998244353;
const int maxn=1e6+10;
const int INF=1e9+10;
inline int qpow(int a,int b) { int ans=1; while(b) { if(b&1) (ans*=a)%=mol; (a*=a)%=mol; b>>=1; } return ans; }
inline int read() {
    int s=0,w=1; char ch=getchar();
    while(ch<'0'||ch>'9') { if(ch=='-') w=-1; ch=getchar(); }
    while(ch>='0'&&ch<='9') { s=s*10+ch-'0'; ch=getchar(); }
    return s*w;
}

int t,n,k,tot,fac[maxn];
vector<int>vec[maxn];
inline void wor() {
    for(re int i=1;i<=tot;i++) vec[i].clear(); 
    tot=n/k;
    for(re int i=1;i<=tot;i++) for(re int j=1;j<=k;j++) vec[i].push_back(j);
    if(tot&1) {
        if(fac[k]*3%k!=0) { puts("No"); return ; }
        int lim=fac[k]*3/k,fg=lim-1-k;
        for(re int i=1;i<=k;i++) { vec[2][i-1]=fg; vec[3][i-1]=lim-i-fg; fg++; if(fg>k) fg=1; }
        for(re int i=1;i<=(tot-3)/2;i++) reverse(vec[3+i].begin(),vec[3+i].end());
    } else {
        for(re int i=1;i<=tot/2;i++) reverse(vec[i].begin(),vec[i].end());
    }
    puts("Yes");
    for(re int i=1;i<=k;i++) {
        for(re int j=1;j<=tot;j++) printf("%lld ",(j-1)*k+vec[j][i-1]);
        puts("");
    }
}
signed main(void) {
    freopen("erp.in","r",stdin); freopen("erp.out","w",stdout);
    int lims=1e6;
    for(re int i=1;i<=lims;i++) fac[i]=fac[i-1]+i;
    t=read();
    while(t--) {
        n=read(); k=read();
        if(n==1) { puts("Yes 1"); continue; }
        if(n/k==1) { puts("No"); continue ; }
        wor();
    }
}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM