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

这是什么神仙思维题?学到了学到了(

题解

posted @ 2021-10-17 00:34  tzc_wk  阅读(18)  评论(0)    收藏  举报