省选模拟(zero4338)

似乎又是挺简单的一场??战神的良心题!!

考场上完全没有思考第一题的性质,导致啥也不会到九点

第二题看完之后认为是dp套dp后来发现可以爆搜

第三题似乎是暴力hash就行,也是找性质题

主要是自己的思维量不够,啥性质也找不到。。。

T1 End Sky II

如果想要判断一个数x是否可行,就是判断所有\(a[i]&x==x\)的数能否将整个序列分成k段并且作为这k段的最大值出现

我们先不考虑判断的方法,如果我们可以判断了,那么就直接按位确定就行了

发现如果区间数量多于k,那么直接合并两个区间答案只会大不会小

所以实际上我们找的就是最大区间划分数,可以用线段树暴力做,也可以根据每一个数是划分到自己这里,还是前一个合法的或者后一个合法的

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=2e5+5;
int n,k,a[N],ans;
int ml[N],mr[N],sta[N],top;
int pre[N],nxt[N],f[N];
bool check(int x){
	memset(f,-0x3f,sizeof(f));f[0]=0;
	fo(i,1,n){
		if((a[i]&x)==x)pre[i]=i;//cerr<<i<<" ";
		else pre[i]=pre[ml[i]];
	}
	fu(i,n,1){
		if((a[i]&x)==x)nxt[i]=i;
		else nxt[i]=nxt[mr[i]];
	}
	fo(i,1,n){
		if((a[i]&x)==x)f[i]=max(f[i],f[i-1]+1);
		else {
			if(pre[i])f[i]=max(f[i],f[pre[i]]);
			if(nxt[i])f[nxt[i]]=max(f[nxt[i]],f[i-1]+1);
		}
	}
	//cerr<<x<<endl;
	return f[n]>=k;
}
signed main(){
	freopen("sky.in","r",stdin);
	freopen("sky.out","w",stdout);
	n=read();k=read();
	fo(i,1,n){
		a[i]=read();
		while(a[sta[top]]<a[i]&&top)mr[sta[top--]]=i;
		sta[++top]=i;
	}while(top)mr[sta[top--]]=n+1;
	fu(i,n,1){
		while(a[sta[top]]<a[i]&&top)ml[sta[top--]]=i;
		sta[++top]=i;
	}while(top)ml[sta[top--]]=0;
	//fo(i,1,n)cerr<<ml[i]<<" "<<mr[i]<<endl;
	fu(i,30,0)if(check(ans|(1<<i)))ans|=(1<<i);
	printf("%d",ans);
}

T2 Hill of Sunflowers

直接搜,咋搜都行!!!

有一个重要的就是如果有一个递增序列,每一个数的取值范围也是递增的

如果范围比较小的话,那么我们枚举每一个数的取值在哪个范围就好了!!

AC_code
#include<bits/stdc++.h>
using namespace std;
#define int 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 int N=10;
const int mod=1e9+7;
int ksm(int x,int y){
	int ret=1;
	while(y){
		if(y&1)ret=ret*x%mod;
		x=x*x%mod;y>>=1;
	}return ret;
}
int n,a[N],ans;
int su[N],so[N],xl[N],b[N],fas;
bool com(int x,int y){return so[x]!=so[y]?so[x]<so[y]:a[x]>a[y];}
map<int,int> mp;int ys[N];
int C(int x,int y){
	if(x<y)return 0;
	int ret=1;
	fo(i,x-y+1,x)ret=ret*i%mod;
	fo(i,1,y)ret=ret*ksm(i,mod-2)%mod;
	return ret;
}
int ji[N],nn;
void dfs_fas(int x){
	if(x==nn+1){
		int las=1,res=1;
		fo(i,1,nn)if(ji[i]!=ji[i-1]){res=res*C(ji[i-1]-ji[las-1],i-las)%mod;las=i;}
		//cout<<res<<" "<<las<<" "<<ji[1]<<" "<<ji[2]<<" "<<ji[3]<<" ";
		res=res*C(ji[nn]-ji[las-1],nn-las+1)%mod;
		fas=(fas+res)%mod;//cout<<res<<endl;
		return ;
	}
	if(x>1){ji[x]=ji[x-1];dfs_fas(x+1);}
	ji[x]=b[x];dfs_fas(x+1);
}
int f[N],fmx,sum;
bool vis[1<<20];
int lsh[N],lh;
void dfs_sort(int x){
	if(x==n+1){
		int now=0;lh=0;
		fo(i,1,n)lsh[++lh]=su[i];//cout<<so[i]<<" ";cout<<"T"<<" ";
		sort(lsh+1,lsh+lh+1);
		lh=unique(lsh+1,lsh+lh+1)-lsh-1;
		fo(i,1,n)so[i]=lower_bound(lsh+1,lsh+lh+1,su[i])-lsh;//cout<<so[i]<<" ";cout<<endl;
		now=so[1];fo(i,2,n)now=(now<<3)+so[i];
		if(vis[now])return ;vis[now]=true;//cout<<now<<" ";
		fo(i,1,n)xl[i]=i;
		sort(xl+1,xl+n+1,com);
		//fo(i,1,n)cout<<xl[i]<<" "<<a[xl[i]]<<endl;
		b[n]=a[xl[n]];fu(i,n-1,1){
			if(so[xl[i]]==so[xl[i+1]])b[i]=min(a[xl[i]],b[i+1]);
			else b[i]=min(a[xl[i]],b[i+1]-1);
			//if(b[i]<=0)return ;
		}
		//fo(i,1,n)cout<<xl[i]<<" "<<b[i]<<" "<<so[xl[i]]<<endl;cout<<"S"<<endl;
		nn=0;fo(i,1,n)if(so[xl[i]]!=so[xl[i-1]])b[++nn]=b[i];
		//fo(i,1,nn)cout<<xl[i]<<" "<<b[i]<<endl;
		//int cnt=0;mp.clear();
		//fo(i,1,n)if(mp.find(b[i])==mp.end())mp[b[i]]=++cnt,ys[cnt]=b[i];
		fas=0;dfs_fas(1);
		memset(f,0,sizeof(f));fmx=0;
		fo(i,1,n){
			f[i]=1;
			fo(j,1,i-1)if(so[j]<so[i])f[i]=max(f[i],f[j]+1);
			fmx=max(fmx,f[i]);
		}
		//cout<<"fas"<<" "<<fas<<" "<<fmx<<endl;
		ans=(ans+fas*fmx)%mod;sum=(sum+fas)%mod;
		return ;
	}
	fo(i,1,n)su[x]=i,dfs_sort(x+1);
}
int anss;
void dfs(int x){
	if(x==n+1){
		memset(f,0,sizeof(f));fmx=0;
		fo(i,1,n){
			f[i]=1;
			fo(j,1,i-1)if(so[j]<so[i])f[i]=max(f[i],f[j]+1);
			fmx=max(fmx,f[i]);
		}anss=(anss+fmx)%mod;
		return ;
	}
	fo(i,1,a[x])so[x]=i,dfs(x+1);
}
signed main(){
	freopen("hill.in","r",stdin);
	freopen("hill.out","w",stdout);
	n=read();
	fo(i,1,n)a[i]=read();
	//dfs(1);cout<<anss<<endl;
	dfs_sort(1);//cout<<sum<<" "<<ans<<endl;
	fo(i,1,n)ans=ans*ksm(a[i],mod-2)%mod;
	printf("%lld",ans);
	return 0;
}

T3 Wonderful Everyday

两个数相加等于一个数,要么是某一个数和答案一样长,另一个数是答案长度减lcp或者再减1

要么是两个数长度都是答案长度减一

暴力hash判断就行了,多换几个模数!!

求lcp就用拓展kmp(z函数)

AC_code
#include<bits/stdc++.h>
using namespace std;
#define ull unsigned long long
#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 int N=2e5+5;
const ull bas=10;
const ll mod=1000000007;
const ll mob=998244353;
const ll moa=998244354;
char chs[N],cht[N];int pp[N*2],lp;
int ls,lt,ss[N],st[N],z[N*2];
ull ba[N],hs[N],ht[N];
ll ca[N],cs[N],ct[N];
ll da[N],ds[N],dt[N];
ll aa[N],as[N],at[N];
bool ck(int l1,int r1,int l2,int r2){
	return ((hs[r1]-hs[l1-1]*ba[r1-l1+1]+hs[r2]-hs[l2-1]*ba[r2-l2+1]==ht[lt])&&
	((cs[r1]-cs[l1-1]*ca[r1-l1+1]%mod+mod+cs[r2]-cs[l2-1]*ca[r2-l2+1]%mod+mod)%mod==ct[lt])&&
	((ds[r1]-ds[l1-1]*da[r1-l1+1]%mob+mob+ds[r2]-ds[l2-1]*da[r2-l2+1]%mob+mob)%mob==dt[lt])&&
	((as[r1]-as[l1-1]*aa[r1-l1+1]%moa+moa+as[r2]-as[l2-1]*aa[r2-l2+1]%moa+moa)%moa==at[lt]));
}
signed main(){
	freopen("wonderful.in","r",stdin);
	freopen("wonderful.out","w",stdout);
	scanf("%s%s",chs+1,cht+1);
	ls=strlen(chs+1);lt=strlen(cht+1);
	fo(i,1,ls)ss[i]=chs[i]-'0';
	fo(i,1,lt)st[i]=cht[i]-'0';
	
	ba[0]=1;fo(i,1,ls)ba[i]=ba[i-1]*bas;
	fo(i,1,ls)hs[i]=hs[i-1]*bas+ss[i];
	fo(i,1,lt)ht[i]=ht[i-1]*bas+st[i];
	
	ca[0]=1;fo(i,1,ls)ca[i]=ca[i-1]*bas%mod;
	fo(i,1,ls)cs[i]=(cs[i-1]*bas%mod+ss[i])%mod;
	fo(i,1,lt)ct[i]=(ct[i-1]*bas%mod+st[i])%mod;
	
	da[0]=1;fo(i,1,ls)da[i]=da[i-1]*bas%mob;
	fo(i,1,ls)ds[i]=(ds[i-1]*bas%mob+ss[i])%mob;
	fo(i,1,lt)dt[i]=(dt[i-1]*bas%mob+st[i])%mob;
	
	aa[0]=1;fo(i,1,ls)aa[i]=aa[i-1]*bas%moa;
	fo(i,1,ls)as[i]=(as[i-1]*bas%moa+ss[i])%moa;
	fo(i,1,lt)at[i]=(at[i-1]*bas%moa+st[i])%moa;
	
	fo(i,1,lt)pp[++lp]=st[i];
	fo(i,1,ls)pp[++lp]=ss[i];
	z[1]=lp;
	for(int i=2,mx=0,id=0;i<=lp;i++){
		if(i<=mx)z[i]=min(z[i-id+1],mx-i+1);
		while(i+z[i]<=lp&&pp[i+z[i]]==pp[1+z[i]])z[i]++;
		if(i+z[i]-1>mx)mx=i+z[i]-1,id=i;
	}
	cerr<<lt<<endl;
	fo(l1,1,ls){
		int r2;
		if(l1+lt+lt-1-z[l1+lt]<=ls&&z[l1+lt]!=lt){
			if(ck(l1,l1+lt-1,l1+lt,r2=l1+lt+lt-1-z[l1+lt])){
				printf("%d %d\n%d %d",l1,l1+lt-1,l1+lt,r2);
				return 0;
			}
		}
		if(l1+lt+lt-2-z[l1+lt]<=ls&&z[l1+lt]!=lt){
			if(ck(l1,l1+lt-1,l1+lt,r2=l1+lt+lt-2-z[l1+lt])){
				printf("%d %d\n%d %d",l1,l1+lt-1,l1+lt,r2);
				return 0;
			}
		}
		if((l1+lt-1+lt-1-1<=ls)&&(ck(l1,l1+lt-2,l1+lt-1,l1+lt-1+lt-1-1))){
			cerr<<l1<<" "<<l1+lt-1<<" "<<l1+lt-1+lt-1-1<<endl;
			printf("%d %d\n%d %d",l1,l1+lt-2,l1+lt-1,l1+lt-1+lt-1-1);
			return 0;
		}
	}
	fo(l2,1,ls){
		if(lt-z[l2+lt]<l2&&z[l2+lt]!=lt){
			if(ck(l2-1-(lt-z[l2+lt])+1,l2-1,l2,l2+lt-1)){
				printf("%d %d\n%d %d",l2-1-(lt-z[l2+lt])+1,l2-1,l2,l2+lt-1);
			}
		}
		if(lt-z[l2+lt]<=l2&&z[l2+lt]!=lt){
			if(ck(l2-1-(lt-z[l2+lt]-1)+1,l2-1,l2,l2+lt-1)){
				printf("%d %d\n%d %d",l2-1-(lt-z[l2+lt]-1)+1,l2-1,l2,l2+lt-1);
			}
		}
	}
	return 0;
}
posted @ 2022-02-22 16:05  fengwu2005  阅读(88)  评论(1编辑  收藏  举报