2020五校聯考NOIP 2 矩陣

2022-01-22 10:06:10 字數 2492 閱讀 7750

咕咕咕到現在~

題面傳送門

題意:給出乙個 \(n\times n\) 的矩陣 \(a\)。要你求有多少個 \(n\times n\) 的矩陣 \(b\) 滿足:

我們考慮條件三。「\(f(b)\) 的字典序小於 \(f(a)\) 的字典序」意味著我們可以列舉第乙個 \(f(a)_i的位置然後統計答案。

假設第乙個不相等的位置為 \(i\) 行 \(j\) 列。那麼矩陣 \(b\) 的前 \(i-1\) 行上的數,以及第 \(i\) 行的前 \(j-1\) 個數,都已經確定下來了,我們的任務就是填好剩下來的 \(n^2-(i-1)\times n-(j-1)\) 個數。

不難注意到,對於後 \(n-i\) 行每行的方案數是固定的,即 \(f_n\),其中 \(f_i\) 表示長度為 \(i\) 的滿足 \(p_j \neq j\) 的排列個數,也就是乙個簡單的錯排數問題。

接下來考慮如何計算填好第 \(i\) 行剩餘的 \(n-j+1\) 個數的方案數,我們可以列舉第 \(j\) 個數是什麼。那麼我們需把這一行剩下來的 \(n-j\) 個數塞入這 \(n-j\) 個位置。再,假設 \(a_,a_,\dots,a_\) 分別記作 \(x_1,x_2,\dots,x_\),第 \(i\) 行剩餘的數分別記作 \(y_1,y_2,\dots,y_\),要求有多少個 \(1\) 到 \(n-j\) 的排列 \(p\) 滿足 \(x_i \neq y_\)。

其實方案數與 \(x_i,y_i\) 具體是什麼數不重要,我們關心的只是有多少個數在 \(x,y\) 中同時出現,也就是官方題解中的「有限制的位置」與「無限制的位置」。

然後就可以 \(dp\) 了,設 \(dp_\) 為有 \(i\) 個有限制的位置和 \(j\) 個無限制的位置的方案數。

若 \(j=0\),顯然 \(dp_=f_i\),直接上公式 \(f_i=\sum\limits_^i\binom\times(-1)^\)

若 \(j \neq 0\),那麼可以用類似組合數遞推的方式。列舉最後乙個無限制的位置上填的數,如果填了乙個無限制的數,有 \(j\) 種方案,無限制的數變為 \(j-1\),即 \(j \times dp_\);如果填了乙個有限制的數,有 \(i\) 種方案,無限制的位置還是 \(j\) 個,原來有限制的數變為無限制的數,即 \(i \times dp_\)。故 \(dp_=j \times dp_+i \times dp_\)。

這樣做是 \(n^3\) 的。不過可以進一步優化:列舉這個位置填的是有限制的數還是沒限制的數,用樹狀陣列/線段樹維護選法,乘上乙個 \(dp\) 係數即可。

#include using namespace std;

#define fz(i,a,b) for(int i=a;i<=b;i++)

#define fd(i,a,b) for(int i=a;i>=b;i--)

#define fill0(a) memset(a,0,sizeof(a))

#define fill1(a) memset(a,-1,sizeof(a))

#define fillbig(a) memset(a,63,sizeof(a))

#define fi first

#define se second

#define int long long

const int mod=998244353;

int n,a[2005][2005],f[2005],c[2005][2005],fac[2005],dp[2005][2005],b[2005][2005];

bool vis1[2005],vis2[2005];

int qpow(int x,int e)

return ans;

}struct node s[2005<<2];

inline void pushup(int k)

inline void build(int k,int l,int r)

inline void add(int k,int ind,int x)

int mid=(s[k].l+s[k].r)>>1;

if(ind<=mid) add(k<<1,ind,x);

else add(k<<1|1,ind,x);

pushup(k);

}inline int query(int k,int l,int r,int x)

signed main()

fac[0]=1;fz(i,1,n) fac[i]=fac[i-1]*i%mod;

fz(i,0,n)

// cout<} for(int i=0;i<=n;i++)

} fz(i,1,n) fz(j,1,n) scanf("%d",&a[i][j]);

fz(i,1,n-1)

// fz(j,1,n) cout<} int ans=0;

fz(i,1,n)

ans=(ans+sum*qpow(f[n],n-i)%mod)%mod;

} printf("%lld\n",ans);

return 0;

}

NOIP提高組五校聯考 string

給出乙個長度為n,由小寫英文本母組成的字串s,求在所有由小寫英文本母組成且長度為n 且恰好有k 位與s 不同的字串中,給定字串t 按照字典序排在第幾位。由於答案可能很大,模10 9 7 輸出。列舉乙個 i 表示當前做到第 i位,而前i 1 位的字元都已經與目標串的前i 1 位相同,那麼對於當前位置可...

NOIP2016提高A組五校聯考2 tree

給一棵n 個結點的有根樹,結點由1 到n 標號,根結點的標號為1。每個結點上有乙個物品,第i 個結點上的物品價值為vi。你需要從所有結點中選出若干個結點,使得對於任意乙個被選中的結點,其到根的路徑上所有的點都被選中,並且選中結點的個數不能超過給定的上限lim。在此前提下,你需要最大化選中結點上物品的...

NOIP2016提高A組五校聯考2 string

description 給出乙個長度為n,由小寫英文本母組成的字串s,求在所有由小寫英文本母組成且長度為n 且恰好有k 位與s 不同的字串中,給定字串t 按照字典序排在第幾位。由於答案可能很大,模10 9 7 輸出。input 第一行為兩個整數n k 第二行乙個字串s 第三行乙個字串t,t即是k位與...