省选模拟(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;
}
QQ:2953174821