2023.2.21模拟赛

T1
题意:
在只含有大写字母的字符串中找到含有26种大写字母的最小长度。若没有输出”QwQ“。
思路:
对于大写字母\(A\) ~ \(Z\)维护它上一次出现的位置,使用双指针, \(i\) 表示右端点, \(j\) 表示左端点,枚举右端点,左端点右移的条件是 \(j\) 不是 \(j\) 位置上的字符最后出现的位置,取 \(i-j+1\) 的最小值。(以上操作在\(A\) ~ \(Z\)全部出现一次后开始,若始终没有出现一次则输出”QwQ“。)
代码:

#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
char a[2000010];
int tong[30];
int n;
int cnt=0;
int ans;
int main(){
	scanf("%s",a+1);
	n=strlen(a+1);
	ans=n;
	for(int i=1;i<=26;i++){
		tong[i]=-1;
	}
	int j=1;
	for(int i=1;i<=n;i++){
		if(tong[a[i]-'A'+1]==-1){
			cnt++;
		}
		tong[a[i]-'A'+1]=i;
		while(j<tong[a[j]-'A'+1]){
			j++;
		}
		if(cnt==26){
			ans=min(ans,i-j+1);
		}
	}
	if(cnt==26){
		cout<<ans;
	}
	else{
		cout<<"QwQ";
	}
	return 0;
}

T2
题意:
起初\(a=1\)\(b=1\)
每回合将\(a\)\(b\)中的一个乘\(k\),另一个乘\(k^{2}\)
\(t\)组询问,问\(x\)\(y\)是否可以成为一次回合的结果。是输出"Yes",否输出"No"。
思路:
\(a\times b=(\prod k)^{3}\) ,所以正确的\(a\times b\)一定是一个三次方数,且\((\prod k)\mid a\)\((\prod k)\mid b\)
代码:

#include<iostream>
#include<cmath>
#include<unordered_map>
#include<cstdio>
#define int long long
using namespace std;
int kd(){
	int x=0,f=1;
	char a=getchar();
	while(a<'0'||a>'9'){
		if(a=='-'){
			f=-1;
		}
		a=getchar();
	}
	while(a>='0'&&a<='9'){
		x=x*10+a-'0';
		a=getchar();
	}
	return x*f;
}
int t;
int gcd(int x,int y){
	if(y==0){
		return x;
	}
	return gcd(y,x%y);
}
unordered_map<long long,bool> mp;
signed main(){
	t=kd();
	for(long long i=1;i<=1000000;i++){
		mp[i*i*i]=1;
	}
	while(t--){
		int x,y;
		x=kd();y=kd();
		long long ans=x*y;
		int g=gcd(x,y);
		x/=g;
		if(gcd(x,g)!=x){
			printf("No\n");
			continue;
		}
		y/=g;
		if(gcd(y,g)!=y){
			printf("No\n");
			continue;
		}
		if(mp[ans]==1){
			printf("Yes\n");
		}
		else{
			printf("No\n");
		}
	}
	return 0;
}

T3
题意:
给一个\(r\times c\)的二维字符串,"*"表示泥地,"."表示草地,用\(1\times k(k\in [1,\infty),k\in Z)\)的木板覆盖,不能覆盖到草地上,泥地可以覆盖多次。问覆盖所有泥地的最少使用模板次数。
思路:
建模,将横向一行,纵向一列的连通块设为点,将一个泥地设为连接它所在横行所表示点和它所在纵列表示点的连边,将一个点覆盖就是将这个连通块用一个木板覆盖,所以就是求这个二分图的最小点覆盖,及最大匹配。
使用匈牙利算法,从一个未匹配点的点开始,一条未匹配边一条匹配边地走,直到到达一个未匹配点(答案加一)或不能继续走,枚举完一个集合中的所有点即可。
代码:

#include<iostream>
#include<cstring>
using namespace std;
int r,c;
char a[60][60];
int line[60];
int row[60];
int cnt=0;
struct node{
	int to;
	int nxt;
}edge[500010];
int head[500010],tot;
void addedge(int u,int v){
	edge[++tot].to=v;
	edge[tot].nxt=head[u];
	head[u]=tot;
}
int vis[500010];
int p[500010];
int ans=0;
int w;
bool dfs(int u,int q){
	for(int i=head[u];i;i=edge[i].nxt){
		int v=edge[i].to;
		if(v==q||p[v]==w){
			continue;
		}
		p[v]=w;
		if(vis[v]==0){
			ans++;
			vis[v]=u;
			return 1;
		}
		else{
			if(dfs(vis[v],v)==1){
				vis[v]=u;
				return 1;
			}
		}
	}
	return 0;
}
int zhan[500010],top;
int main(){
	cin>>r>>c;
	for(int i=1;i<=r;i++){
		scanf("%s",a[i]+1);
	}
	for(int i=0;i<=r+1;i++){
		a[i][0]='.';
		a[i][c+1]='.';
	}
	for(int j=0;j<=c+1;j++){
		a[0][j]='.';
		a[r+1][j]='.';
	}
	for(int i=1;i<=r;i++){
		for(int j=1;j<=c;j++){
			if(a[i][j]=='*'&&a[i-1][j]=='.'){
				line[j]=++cnt;
				zhan[++top]=cnt;
			}
			if(a[i][j]=='*'&&a[i][j-1]=='.'){
				row[i]=++cnt;
			}
			if(a[i][j]=='*'){
				addedge(line[j],row[i]);
			}
		}
	}
	for(int i=1;i<=top;i++){
		w=i;
		dfs(zhan[i],0);
	}
	cout<<ans;
	return 0;
}
posted @ 2023-02-21 20:53  zzzzzz2  阅读(39)  评论(0)    收藏  举报