省选模拟17

今天考的不是联考的试题,而是ZZ_zuozhe的题,题目质量好高!!!

第一题,想到了用bitset做,然后发现枚举的有用的只有是1的位,于是想到用set,但是复杂度瓶颈在于转移时的赋值操作,没想到可以用主席树

第二题,妈呀想着是阶乘然后就写成没阶乘了......

第三题,写了个背包,于是只有35分

T1 最短路

发现增加一条路就是将一段连续的1变成0,前面加个1,可以用线段树二分

转移就是直接赋值,这里用dij的时候,用set当堆,这样比较函数比较好写参数可以改

AC_code
#include<bits/stdc++.h>
using namespace std;
#define fo(i,x,y) for(int i=(x);i<=(y);i++)
#define fu(i,x,y) for(int i=(x);i>=(y);i--)
int read(){
	int s=0,t=1;char ch=getchar();
	while(!isdigit(ch)){if(ch=='-')t=-1;ch=getchar();}
	while(isdigit(ch)){s=s*10+ch-'0';ch=getchar();}
	return s*t;
}
const int N=1e5+5;
const int M=2e5+1e3;
const int mod=1e9+7;
int ksm(int x,int y){
	int ret=1;
	while(y){
		if(y&1)ret=1ll*ret*x%mod;
		x=1ll*x*x%mod;y>>=1;
	}return ret;
}
int mo(int x){return x>=mod?x-mod:x;}
int fro[M];int all(int l,int r){if(l==0)return fro[r];return mo(fro[r]-fro[l-1]+mod);}
struct ZXS{
	struct POT{int ls,rs,sum;}tr[M*100];
	int seg;
	int newpot(int x){tr[++seg]=tr[x];return seg;}
	void pushup(int x){
		//if(!tr[x].ls&&!tr[x].rs)return ;
		tr[x].sum=mo(tr[tr[x].ls].sum+tr[tr[x].rs].sum);
	}
	void ins(int &x,int px,int l,int r,int ql,int qr,int v){
		x=newpot(px);if(ql>qr)return ;
		if(ql<=l&&r<=qr){
			tr[x].ls=tr[x].rs=0;
			if(v)tr[x].sum=all(l,r);
			else tr[x].sum=0;
			return ;
		}
		int mid=l+r>>1;
		if(ql<=mid)ins(tr[x].ls,tr[px].ls,l,mid,ql,qr,v);
		if(qr>mid)ins(tr[x].rs,tr[px].rs,mid+1,r,ql,qr,v);
		pushup(x);return ;
	}
	int query_mxlen(int x,int l,int r,int ql){
		if(ql<=l){
			if(tr[x].sum==all(l,r))return r;
			if(l==r||!tr[x].sum)return l-1;
			int mid=l+r>>1;
			if(tr[tr[x].ls].sum==all(l,mid))return query_mxlen(tr[x].rs,mid+1,r,ql);
			else return query_mxlen(tr[x].ls,l,mid,ql);
		}
		if(tr[x].sum==all(l,r))return r;
		if(!tr[x].sum)return ql-1;
		int mid=l+r>>1,ret=0;
		if(ql<=mid)ret=query_mxlen(tr[x].ls,l,mid,ql);
		if(ret==mid||ql>mid)return query_mxlen(tr[x].rs,mid+1,r,ql);
		else return ret;
	}
	bool comp(int x,int y,int l,int r){//x<y true
		if(tr[x].sum==tr[y].sum)return false;
		if(tr[x].sum==all(l,r))return false;
		if(!tr[x].sum)return true;
		if(tr[y].sum==all(l,r))return true;
		if(!tr[y].sum)return false;
		if(l==r)return tr[x].sum<tr[y].sum;
		int mid=l+r>>1;
		if(tr[tr[x].rs].sum==tr[tr[y].rs].sum)return comp(tr[x].ls,tr[y].ls,l,mid);
		else return comp(tr[x].rs,tr[y].rs,mid+1,r);
	}
}zxs;
int rt[N];
int n,m,R=2e5+20,s,t;
bool vis[N],ist[N];
struct node{
	int x;
	bool operator < (node a)const{
		if(zxs.tr[rt[x]].sum==zxs.tr[rt[a.x]].sum)return x<a.x;
		return zxs.comp(rt[x],rt[a.x],1,R);
	}
};
set<node> st;
struct E{int to,nxt,val;}e[M*2];
int head[N],rp;
void add_edg(int x,int y,int z){
	e[++rp].to=y;e[rp].nxt=head[x];
	e[rp].val=z;head[x]=rp;
}
signed main(){
	freopen("hellagur.in","r",stdin);
	freopen("hellagur.out","w",stdout);
	n=read();m=read();
	fro[0]=1;fo(i,1,R)fro[i]=(fro[i-1]+ksm(2,i))%mod;
	fo(i,1,m){
		int x=read(),y=read(),z=read();
		add_edg(x,y,z);add_edg(y,x,z);
		//if(z==0)cerr<<"SB"<<endl;
	}
	s=read();t=read();rt[s]=++zxs.seg;
	fo(i,1,n)if(i!=s)zxs.ins(rt[i],rt[s],1,R,1,R,1);
	st.insert(node{s});ist[s]=true;
	while(st.size()){
		int x=st.begin()->x;st.erase(st.begin());
		if(vis[x])continue;
		vis[x]=true;ist[x]=false;
		for(int i=head[x];i;i=e[i].nxt){
			int y=e[i].to,tmp,r,l=e[i].val;
			if(vis[y])continue;
			r=zxs.query_mxlen(rt[x],1,R,l);
			zxs.ins(tmp,rt[x],1,R,l,r,0);
			zxs.ins(tmp,tmp,1,R,r+1,r+1,1);
			if(zxs.comp(tmp,rt[y],1,R)){
				if(ist[y])st.erase(node{y});
				ist[y]=true;rt[y]=tmp;
				st.insert(node{y});
			}
		}
	}
	if(zxs.tr[rt[t]].sum==all(1,R))printf("-1");
	else printf("%d",zxs.tr[rt[t]].sum);
}

T2 集合

发现有可能的大小是n,n-1,n-2

奇数的话,还有n-3,用异或hash表示

AC_code
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define fo(i,x,y) for(int i=(x);i<=(y);i++)
#define fu(i,x,y) for(int i=(x);i>=(y);i--)
int read(){
	int s=0,t=1;char ch=getchar();
	while(!isdigit(ch)){if(ch=='-')t=-1;ch=getchar();}
	while(isdigit(ch)){s=s*10+ch-'0';ch=getchar();}
	return s*t;
}
const ll inf=1e18;
random_device pyt;
mt19937 you(pyt());
ll rd(ll l,ll r){
	return rand()%inf;
	uniform_int_distribution<> ee(l,r);
	return ee(you)*ee(you);
}
const int N=1e6+5;
int n;
unordered_map<ll,int> mp;
ll vl[100005],val[N],tmp;
int p[100005],cnt,mn[N];
bool vis[N];
void init_p(){
	fo(i,2,n){
		if(!vis[i]){
			p[++cnt]=i;
			vl[cnt]=rd(1,inf);
			mn[i]=cnt;
		}
		for(int j=1;j<=cnt&&i*p[j]<=n;j++){
			vis[i*p[j]]=true;mn[i*p[j]]=j;
			if(i%p[j]==0)break;
		}
	}
}
int ck2(int n){tmp=0;
	fo(i,1,n)tmp^=val[i];
	fo(i,1,n)if(mp.find(tmp^val[i])!=mp.end()&&mp[tmp^val[i]]!=i)return i;
	return false;
}
int ck1(int n){tmp=0;
	fo(i,1,n)tmp^=val[i];
	fo(i,1,n)if((tmp^val[i])==0)return i;
	return false;
}
bool ck0(int n){tmp=0;
	fo(i,1,n)tmp^=val[i];
	return !tmp;
}
signed main(){
	freopen("mountain.in","r",stdin);
	freopen("mountain.out","w",stdout);
	n=read();int res;srand(time(0));
	init_p();
	fo(i,1,n){int now=i;ll hs=0;
		while(now!=1)hs^=vl[mn[now]],now/=p[mn[now]];
		val[i]=val[i-1]^hs;mp[val[i]]=i;
	}
	if(n&1)n--;
	if(ck0(n)){
		printf("%d\n",n);
		fo(i,1,n)printf("%d ",i);
		return 0;
	}
	if(res=ck1(n)){
		printf("%d\n",n-1);
		fo(i,1,n)if(i!=res)printf("%d ",i);
		return 0;
	}
	if(res=ck2(n)){
		printf("%d\n",n-2);int sm=0;
		fo(i,1,n)if(i!=res&&i!=mp[tmp^val[res]])printf("%d ",i);
		return 0;
	}
	mp.erase(val[n--]);res=ck2(n);
	printf("%d\n",n-2);//mp.erase(val[n]);
	fo(i,1,n)if(i!=res&&i!=mp[tmp^val[res]])printf("%d ",i);
	return 0;
}

T3 食材

这个不可改,根本看不懂题解诶......

上一篇:ARC135 题解


下一篇:C# 实例解释面向对象编程中的开闭原则