test20231104

T1

简单题,可以做到 \(n^2\) 但是没必要, \(n^3\) 已经很快了。

int n,m;
char a[550][550];
int h[550][550],ans;
signed main(){
	n=read();m=read();
	up(i,1,n){
		scanf("%s",a[i]+1);
	}
	up(i,1,n){
		up(j,1,m){
			if(a[i][j]=='.')h[i][j]=h[i-1][j]+1;
			else h[i][j]=0;
		}
		up(j,1,m){
			if(h[i][j]==0)continue;
			int L=j,R=j,x=h[i][j];
			while(R<m&&h[i][R+1]>=x)R++;
			while(L>1&&h[i][L-1]>=x)L--;
			ans=max(ans,2*(R-L+1+x)-1);
		}
	}
	cout<<ans;
	return 0;
}

T2

tmd,看到只有五个数,想着直接推数学公式,然推退了两个小时,然后打了个 \(O(n)\) 的 dp,然后看出来了要用矩阵快速幂,但是写挂了,而且也没有时间调代码了。

先简单写一个暴力 dp。

	cnt[0][1]=1;
	cnt[0][0]=1;
	g[0][0]=e;
	g[0][1]=d;
	up(i,1,30){
		int pre1=i-a;
		if(pre1>=0){
			cnt[i][1]=(cnt[i][1]+cnt[pre1][1])%mod;
			g[i][1]=(g[i][1]+g[pre1][1]+cnt[pre1][1]*d)%mod;
		} 
		int pre2=i-b;
		if(pre2>=0){
			cnt[i][1]=(cnt[i][1]+cnt[pre2][0])%mod;
			cnt[i][0]=(cnt[i][0]+cnt[pre2][1])%mod;	
			g[i][1]=(g[i][1]+g[pre2][0]+cnt[pre2][0]*d)%mod;
			g[i][0]=(g[i][0]+g[pre2][1]+cnt[pre2][1]*e)%mod;		
		} 
		int pre3=i-c;
		if(pre3>=0){
			cnt[i][0]=(cnt[i][0]+cnt[pre3][0])%mod;	
			g[i][0]=(g[i][0]+g[pre3][0]+cnt[pre3][0]*e)%mod;		
		} 
	} 

我们发现 \(a,b,c\le30\),所以我们可以用一个矩阵把 \([i-30,i]\) 的情况记录下来,然后构造转移矩阵。

难吗?真的不难,只是繁琐而已。

int n,a,b,c,d,e;
int cnt[55][2],g[55][2];
struct mat{
	int a[205][205];
	mat(){
		memset(a,0,sizeof a);
	}
	inline mat operator*(const mat&rhs)const{
		mat res;
		up(i,1,130){
			up(j,1,130){
				up(k,1,130){
					res.a[i][j]=(res.a[i][j]+a[i][k]*rhs.a[k][j])%mod;
				}
			}
		}
		return res;
	}
	inline void init(){
		up(i,1,190)a[i][i]=1;
	}
}A,B;
inline mat ksm(mat a,int b){
	mat res;
	res.init();
	while(b){
		if(b&1)res=res*a;
		a=a*a;
		b>>=1;
	}
	return res;
}
signed main(){
	n=read();
	a=read();b=read();c=read();
	d=read();e=read();
	
	cnt[0][1]=1;
	cnt[0][0]=1;
	g[0][0]=e;
	g[0][1]=d;
	up(i,1,30){
		int pre1=i-a;
		if(pre1>=0){
			cnt[i][1]=(cnt[i][1]+cnt[pre1][1])%mod;
			g[i][1]=(g[i][1]+g[pre1][1]+cnt[pre1][1]*d)%mod;
		} 
		int pre2=i-b;
		if(pre2>=0){
			cnt[i][1]=(cnt[i][1]+cnt[pre2][0])%mod;
			cnt[i][0]=(cnt[i][0]+cnt[pre2][1])%mod;	
			g[i][1]=(g[i][1]+g[pre2][0]+cnt[pre2][0]*d)%mod;
			g[i][0]=(g[i][0]+g[pre2][1]+cnt[pre2][1]*e)%mod;		
		} 
		int pre3=i-c;
		if(pre3>=0){
			cnt[i][0]=(cnt[i][0]+cnt[pre3][0])%mod;	
			g[i][0]=(g[i][0]+g[pre3][0]+cnt[pre3][0]*e)%mod;		
		} 
	} 
	if(n<=30){
		cout<<(g[n][0]+g[n][1])%mod<<endl;
		return 0;
	}
	n-=30;
	up(i,1,31)A.a[1][i]=cnt[i-1][0];
	up(i,32,62)A.a[1][i]=cnt[i-32][1];
	up(i,63,93)A.a[1][i]=g[i-63][0];
	up(i,94,124)A.a[1][i]=g[i-94][1];
	up(i,0,3){
		up(j,0,29){
			B.a[i*31+1+j+1][i*31+1+j]=1;
		}
	}
	B.a[31-c+1][31]=1;
	B.a[31+31-b+1][31]=1;
	B.a[31+31-a+1][62]=1;
	B.a[31-b+1][62]=1;
	B.a[31-c+1][93]=e;
	B.a[31+31-b+1][93]=e;
	B.a[31*2+31-c+1][93]=1;
	B.a[31*3+31-b+1][93]=1;
	B.a[31+31-a+1][124]=d;
	B.a[31-b+1][124]=d;
	B.a[31*3+31-a+1][124]=1;
	B.a[31*2+31-b+1][124]=1;
	A=A*ksm(B,n);
	cout<<(A.a[1][93]+A.a[1][124])%mod;
	return 0;
}

T3

简单题,字典树上 dfs 就行了。

int n;
int tr[M][26],dep[M],tim[M];
int cnt;
inline void insert(string s){
	int p=0;
	up(i,0,s.size()-1){
		int ch=s[i]-'a';
		if(!tr[p][ch])tr[p][ch]=++cnt,dep[cnt]=dep[p]+1;
		p=tr[p][ch];
		tim[p]++;
	}
}
int sz[M],del[M];
inline void insert2(string s){
	int p=0;
	up(i,0,s.size()-1){
		int ch=s[i]-'a';
		if(!tr[p][ch])break;
		p=tr[p][ch];
	}
	sz[p]++;
}
int ans;
inline void dfs(int u){
	up(i,0,25){
		if(tr[u][i]==0)continue;
		dfs(tr[u][i]);
		sz[u]+=sz[tr[u][i]];
		del[u]+=del[tr[u][i]];
	}
	tim[u]-=del[u];
	if(sz[u]>=tim[u]){
		ans+=tim[u]*dep[u];
		sz[u]-=tim[u];
		del[u]+=tim[u];
	}
	else {
		ans+=sz[u]*dep[u];
		del[u]+=sz[u];
		sz[u]=0;
	} 
}
signed main(){
	ios_base::sync_with_stdio(0);
	cin.tie(0);cout.tie(0);
	cin>>n;
	string s;
	up(i,1,n){
		cin>>s;
		insert(s);
	}
	up(i,1,n){
		cin>>s;
		insert2(s);
	}
	dfs(0);
	cout<<ans<<endl;;
	return 0;
}

T4

以 T4 的水准来说应该算是一道简单题,思维并不复杂。

重点:抽屉原理,一个区间不会长度超过 \(14\)

每次操作等于是把幂次乘上 \(3\)

由于 \(a_i\) 到最后一定是为 \(a_i^{3^k}\),所以我们可以直接暴力倍增,然后分解 \(k\) 就行了。

int n,m,v,phi;
int a[N];
int dp[N][22];
inline void init(){
    up(i,0,v-1)dp[i][0]=i*i*i%v;
    up(j,1,20){
        up(i,0,v-1){
           dp[i][j]=dp[dp[i][j-1]][j-1];
        }
    }
}
struct SegmentTree{
    struct node{
        int l,r,tag;
    }tr[N<<2];
    inline void build(int k,int l,int r){
        tr[k].l=l;tr[k].r=r;tr[k].tag=0;
        if(l==r)return;
        int mid=(l+r)>>1;
        build(lc,l,mid);
        build(rc,mid+1,r);
    }
    inline void push_down(int k){
        if(tr[k].tag!=0){
            tr[lc].tag=tr[k].tag+tr[lc].tag;
            tr[rc].tag=tr[rc].tag+tr[k].tag;
            tr[k].tag=0;
        }
    }
    inline void plus(int k,int l,int r){
        if(tr[k].l>=l&&tr[k].r<=r){
            tr[k].tag++;
            return;
        }
        int mid=(tr[k].l+tr[k].r)>>1;
        push_down(k);
        if(mid>=l)plus(lc,l,r);
        if(mid<r)plus(rc,l,r);
    }
    inline void clac(int&ans,int&r){
        int j=20;
        while(j>=0){
            if(r>=(1<<j)){
                ans=dp[ans][j];
                r-=(1<<j);
                if(r==0)break;
            }
            j--;
        }
        return;
    }
    inline void ask(int k,int l,int r){
        if(tr[k].l==tr[k].r){
            clac(a[tr[k].l],tr[k].tag);
            return;
        }
        int mid=(tr[k].l+tr[k].r)>>1;
        push_down(k);
        if(mid>=l)ask(lc,l,r);
        if(mid<r)ask(rc,l,r);
    }
}T;
bool flag;
bool vis[N];
int sta[N],cnt;
inline void dfs1(int u,int lim,int sum,bool lead){
    if(flag)return;
    if(u==lim+1){
        if(lead==1){
            if(sum==0)flag=1;
            else if(sum>0&&!vis[sum]){
                vis[sum]=1;
                sta[++cnt]=sum;
            }
        }
        return;
    }
    dfs1(u+1,lim,sum+a[u]+1,1);
    dfs1(u+1,lim,sum-a[u]-1,1);
    dfs1(u+1,lim,sum,lead);
}
inline void dfs2(int u,int lim,int sum,bool lead){
    if(flag)return;
    if(u==lim+1){
        if(lead==1){
            if(sum==0)flag=1;
            else if(sum>0&&vis[sum])flag=1;
        }
        return;
    }
    dfs2(u+1,lim,sum,lead);
    dfs2(u+1,lim,sum+a[u]+1,1);
    dfs2(u+1,lim,sum-a[u]-1,1);
}
signed main(){
	n=read();m=read();v=read();
    init();
    up(i,1,n)a[i]=read();
    T.build(1,1,n);
    int l,r,op;
    while(m--){
        op=read();
        if(op==1){
            l=read();r=read();
            if(r-l+1>=14)puts("Yes");
            else{
                T.ask(1,l,r);
                flag=0;cnt=0;
                int mid=(l+r)>>1;
                dfs1(l,mid,0,0);
                dfs2(mid+1,r,0,0);
                if(flag)puts("Yes");
                else puts("No");
                up(i,1,cnt)vis[sta[i]]=0;
            }
        }
        else{
            l=read(),r=read();
            T.plus(1,l,r);
        }
    }
    return 0;
}

image

posted @ 2023-11-05 10:02  LiQXing  阅读(41)  评论(0)    收藏  举报