2023年石门中学NOIP模拟测试(2023.10.13)
再次被打爆...
T1
有一个 \(n\ast m\) 的矩阵 \(a\),矩阵的每个元素是 \(1,2,3\)。可以任意交换两行,问是否经过若干次
交换,使得每一列都是单调不减的。\(n,m\leq 1e2\)。
sb 题,写个 \(\text{vector}\) 排序还挂了,服了。
T2
oh,我会推柿子。oh,我不会 \(\text{Lucas}\) 😃 写了 \(\text{1h}\) 纯是 fw。
T3

数据范围 \(n\leq 20,m\leq 3\times 10^3\)。
md,我是唇笔,设出状态不会转移。
首先上升子序列只与值的相对关系有关,我们并不关心具体值,所以我们可以用 \([1,n]\) 值域的数表示长度为 \(n\) 的所有 \([1,m]\) 取值的序列,答案最后我们再乘上个组合数就行。那我们现在有个较为暴力的 \(\text{dp}\) 就是考虑一次填完同一个数,然后对于你填了数的判断上升子序列是否合法,枚举子集转移即可,时间复杂度 \(O(3^n\times n^2)\)。
我们继续考虑优化:将子集枚举提出来,变成一位位考虑:设 \(dp_{i,j,S}\) 表示正在考虑 \(i\) 的填数,从后往前考虑第 \(j\) 个位置填不填数字 \(i\),当前填了数的集合是 \(S\) 的方案数。转移枚举位。但有个细节,这样我们其实不知道 \(i\) 有没有填(因为有转移可能一次也没有填的情况)。那我们这时候统计出的答案就是最多用了 \(i\) 个不同数字的方案数。我们小小容斥一下:设 \(Ans\) 为刚好,那么 \(Ans_i=ans_i-\sum\limits_{j<i}Ans_j\times \binom{i}{j}\)。时间复杂度 \(O(2^n\times n^2)\)。
Code
#include<bits/stdc++.h>
#define il inline
#define rint register int
#define int long long
using namespace std;
const int N=1e5+10,mod=998244353;
char *p1,*p2,buf[N];
#define nc() (p1==p2 && (p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++)
#define gc() getchar()
il int rd(){
int x=0,f=1;
char ch=gc();
while(!isdigit(ch)){if(ch=='-')f=-1;ch=gc();}
while(isdigit(ch))x=(x<<3)+(x<<1)+(ch^48),ch=gc();
return x*f;
}
int n,m;
int a[30],dp[1<<20|1][20][2];
int ans[30];
int pw[N],inv[N];
int ksm(int x,int y){int s=1;while(y){if(y&1)s=s*x%mod;x=x*x%mod;y>>=1;}return s;}
int C(int n,int m){return pw[n]*inv[n-m]%mod*inv[m]%mod;}
int pres[N];
void pre(int n){
inv[0]=pw[0]=1;
for(int i=1; i<=n; ++i)pw[i]=pw[i-1]*i%mod;
inv[n]=ksm(pw[n],mod-2);
for(int i=n-1; i>=1; --i)inv[i]=inv[i+1]*(i+1)%mod;
}
void add(int &x,int y){x=(x+y)%mod;return;}
void Main(){
n=rd(),m=rd();
for(int i=0; i<n; ++i)a[i]=rd();
for(int i=0; i<(1<<n); ++i){
for(int j=0; j<n; ++j)if((i>>j)&1)pres[i]=max(pres[i],a[j]);
}
pre(max(n,m));
dp[0][n-1][0]=1;
for(int id=0,i=1; i<=n; ++i,id^=1){
for(int j=n-1; j>=0; --j){
for(int s=0; s<(1<<n); ++s){
if(dp[s][j][id]){
// cout<<i<<' '<<s<<' '<<j<<endl;
if(j)add(dp[s][j-1][id],dp[s][j][id]);
else add(dp[s][n-1][id^1],dp[s][j][id]);
if(!((s>>j)&1)&&pres[s&((1<<j)-1)]+1==a[j]){
if(j)add(dp[s|(1<<j)][j-1][id],dp[s][j][id]);
else add(dp[s|(1<<j)][n-1][id^1],dp[s][j][id]);
}
dp[s][j][id]=0;
}
}
}
ans[i]=dp[(1<<n)-1][n-1][id^1];
// cout<<ans[i]<<endl;
}
int Ans=0;
for(int i=1; i<=n; ++i){
for(int j=1; j<i; ++j)ans[i]=(ans[i]-C(i,j)*ans[j]%mod+mod)%mod;
(Ans+=ans[i]*C(m,i)%mod)%=mod;
}
cout<<Ans;
}
signed main(){
freopen("c.in","r",stdin);
freopen("c.out","w",stdout);
int T=1;
while(T--)Main();
return 0;
}
T4

数据范围:\(n,q,a_i\leq 10^5\)。
写个牛马,烂了烂了。

浙公网安备 33010602011771号