2021.10.15 模拟赛题解
再一次垫底,彻底自闭了/ll
全方位 dd NOI(时间比 NOI 短,难度比 NOI 大,题数比 NOI 多)的 nb 模拟赛
T1
这是什么神仙 set 乱搞题?学到了学到了(
首先显然答案满足可二分性,因此考虑二分答案 \(x\),检验时考虑将合并转化为分裂的过程,即,每次要将 \(x\) 分裂为 \(n\) 个数 \(c_1,c_2,\cdots,c_n\),满足 \(c_i\ge a_i\)。我们考虑设当前分裂出来的数集为 \(S\),待匹配的数集为 \(T\),那么我们考虑每次取出 \(S,T\) 中最大的元素,分别设为 \(mxs,mxt\),设 \(b\) 中最小的元素为 \(b_1\),如果 \(mxs-mxt<b_1\),那么我们只能在 \(S\) 中找到 \(\ge mxt\) 且最小的数与 \(mxt\) 匹配,如果找不到则直接返回 \(0\),因为无论如何我们是不可能分裂 \(mxs\) 的,否则就将 \(mxs\) 分裂为 \(m\) 个元素压入 \(S\),如此进行下去直到 \(|S|=|T|\) 即可。最后检验 \(S,T\) 中元素是否满足从小到大排序后,对应位置上的数都有 \(S_i\ge T_i\),如果有则返回 \(1\),否则返回 \(0\)。
T2
这是什么神仙线性代数题?这是什么神仙哈希方法?学到了学到了(
注意到对于每个点 \(i\),答案就是 \(1\to i\) 最小割大小。
直接暴力 dinic 大概可以拿到 40 分的好成绩。考虑优化。显然最小割大小 \(\le d\),因此考虑对 DAG 进行一遍拓扑排序,对于每条边 \((u,v)\) 我们给它赋上一个随机向量,并且这个向量可以写成 \(u\) 的向量空间中向量的线性组合,并将其插入 \(v\) 的向量空间,那么对于每个点,答案就是其线性空间的秩。
时间复杂度 \((m+n)d^2\)。
int _rand(){return rand()&32767;}
int Rand(){return _rand()*32768+_rand();}
int qpow(int x,int e){
int ret=1;
for(;e;e>>=1,x=1ll*x*x%MOD) if(e&1) ret=1ll*ret*x%MOD;
return ret;
}
const int MAXN=1e5;
const int MAXM=2e5;
const int MAXD=10;
int n,m,hd[MAXN+5],to[MAXM+5],nxt[MAXM+5],ec=0,d=0;
void adde(int u,int v){to[++ec]=v;nxt[ec]=hd[u];hd[u]=ec;}
struct vec{
vector<int> v;
vec(){v.clear();}
vec operator +(const vec &rhs){
vec res;res.v.resize(d);
for(int i=0;i<d;i++) res.v[i]=(v[i]+rhs.v[i])%MOD;
return res;
}
vec operator -(const vec &rhs){
vec res;res.v.resize(d);
for(int i=0;i<d;i++) res.v[i]=(v[i]-rhs.v[i]+MOD)%MOD;
return res;
}
vec operator *(const int &rhs){
vec res;res.v.resize(d);
for(int i=0;i<d;i++) res.v[i]=1ll*v[i]*rhs%MOD;
return res;
}
};
struct lbase{
vec b[MAXD+3];
void init(){for(int i=0;i<d;i++) b[i].v.resize(d,0);}
void insert(vec v){
for(int i=0;i<d;i++) if(v.v[i]){
if(!b[i].v[i]) return b[i]=v,void();
else{
int iv=1ll*(MOD-qpow(b[i].v[i],MOD-2))*v.v[i]%MOD;
for(int j=0;j<d;j++) v.v[j]=(v.v[j]+1ll*b[i].v[j]*iv)%MOD;
}
}
}
int calc(){
int sum=0;
for(int i=0;i<d;i++) sum+=(b[i].v[i]>0);
return sum;
}
vec gen(){
vec ret;ret.v.resize(d);
for(int i=0;i<d;i++) ret=ret+b[i]*Rand();
return ret;
}
} b[MAXN+5];
int main(){
freopen("path.in","r",stdin);
freopen("path.out","w",stdout);
srand(20211015);scanf("%d%d",&n,&m);
for(int i=1,u,v;i<=m;i++) scanf("%d%d",&u,&v),adde(v,u),d+=(u==1);
for(int i=1;i<=n;i++) b[i].init();
for(int i=0;i<d;i++) b[1].b[i].v[i]=1;
for(int i=2;i<=n;i++){
for(int e=hd[i];e;e=nxt[e]){
int fr=to[e];
b[i].insert(b[fr].gen());
} printf("%d\n",b[i].calc());
}
return 0;
}
T3
这是什么神仙数据结构?学到了学到了(
T4
这是什么神仙思维题?学到了学到了(