The 45th ICPC Asia East Continent Final Contest部分题解(F,L,K,B)

F. Rooks

题意:

给定庞教授的 \(n_1\) 个车和寿教授的 \(n_2\) 个车(均在二维平面整数坐标上,位置互不重复),判断每个车是否被攻击。攻击条件:两车分属不同棋手,横坐标或纵坐标相同,且两点连线间无其他车。

思路:

用map模拟每行每列,二分查找一下。

代码

点击查看代码
void solve() {
	int n1,n2;
	cin>>n1>>n2;
	vector<PII>q1,q2;
	vector<int>ans1(n1,0),ans2(n2,0);
	for(int i=1;i<=n1;i++){
		int x,y;
		cin>>x>>y;
		q1.push_back({x,y});
	}
	for(int i=1;i<=n2;i++){
		int x,y;
		cin>>x>>y;
		q2.push_back({x,y});
	}
	map<int,vector<PIII>>qx,qy;
	for(int i=0;i<q1.size();i++){
		qx[q1[i].first].push_back({q1[i].second,{1,i}});
		qy[q1[i].second].push_back({q1[i].first,{1,i}});
	}
	for(int i=0;i<q2.size();i++){
		qx[q2[i].first].push_back({q2[i].second,{2,i}});
		qy[q2[i].second].push_back({q2[i].first,{2,i}});
	}
	for(auto &[x,y]:qx){
		sort(y.begin(),y.end());
		for(int i=0;i<y.size();i++){
			if(i){
				if(y[i-1].second.first!=y[i].second.first){
					if(y[i].second.first==1){
						ans1[y[i].second.second]=1;
					}else{
						ans2[y[i].second.second]=1;
					}
				}
			}
			if(i+1<y.size()){
				if(y[i+1].second.first!=y[i].second.first){
					if(y[i].second.first==1){
						ans1[y[i].second.second]=1;
					}else{
						ans2[y[i].second.second]=1;
					}
				}
			}
		}
	}
	for(auto &[x,y]:qy){
		sort(y.begin(),y.end());
		for(int i=0;i<y.size();i++){
			if(i){
				if(y[i-1].second.first!=y[i].second.first){
					if(y[i].second.first==1){
						ans1[y[i].second.second]=1;
					}else{
						ans2[y[i].second.second]=1;
					}
				}
			}
			if(i+1<y.size()){
				if(y[i+1].second.first!=y[i].second.first){
					if(y[i].second.first==1){
						ans1[y[i].second.second]=1;
					}else{
						ans2[y[i].second.second]=1;
					}
				}
			}
		}
	}
	for(int i=0;i<n1;i++){
		cout<<ans1[i];
	}cout<<endl;
	for(int i=0;i<n2;i++){
		cout<<ans2[i];
	}cout<<endl;
	
}

L. Square

题意:给定整数序列 \(a_1,a_2,...,a_n\),需构造正整数序列 \(t_1,t_2,...,t_n\),满足对每个 \(1≤i<n\)\(a_i×t_i×a_{i+1}×t_{i+1}\) 是完全平方数,且 \(t_1×t_2×...×t_n\) 最小,输出该最小值对 \(10^9+7\) 取模的结果。

思路:

分别对每个质因数分开讨论。
不妨令 \(a_i=p^{k_i}\),如要满足条件,则所有 \(k_i\) 的奇偶性要相同,否则存在 \(j\) 满足 \(a_j×a_{j+1}=p^{k_j+k_{j+1}}\)\(k_j+k_{j+1}\) 为奇数,与条件相悖。
则对每个质因数,选择全奇数和全偶数代价更小的那个,累乘得到答案。

代码

点击查看代码
int minp[N];
int prime[N];
int cnt;
void sieve() {
	cnt=0;
	for (int i = 2; i < N; ++i) {
		if (minp[i] == 0) {
			minp[i] = i;
			prime[++cnt]=i;
		}
		for (int j=1;j<=cnt;j++) {
			int p=prime[j];
			if (p * i >= N) break;
			minp[p * i] = p;
			if (i % p == 0) break;
		}
	}
}
int qpow(int a, int b) {
	int r = 1;
	while (b) {
		if (b & 1) r = r * a % mod;
		a = a * a % mod;
		b >>= 1;
	}
	return r;
}
vector<int>g[N];
int a[N];
void solve() {
	sieve();
	int n;
	cin>>n;
	for(int i=1;i<=n;i++){
		cin>>a[i];
		while(a[i]>1){
			int p=minp[a[i]];
			int s=0;
			while(a[i]%p==0){
				a[i]/=p;
				s++;
			}
			if(s%2){
				int d=lower_bound(prime+1,prime+1+cnt,p)-prime;
				g[d].push_back(i);
			}
		}
	}
	int ans=1;
	for(int i=1;i<=cnt;i++){
		if(g[i].size()){
			ans*=qpow(prime[i],min((int)g[i].size(),n-(int)g[i].size()));
			ans%=mod;
		}
	}
	cout<<ans<<endl;
}

K. Allin

题意:

两个玩家,每个玩家 \(2\) 张牌,加上公共牌 \(5\) 张,每个玩家用自己的 \(2\) 张牌和公共牌 \(5\) 张选出 \(5\) 张,组出最好的牌型,比较牌型大小。从小到大分别为高牌,一对,两对,三条,顺子,同花,葫芦,四条,同花顺,皇家同花顺。

给定 Wolf Chicken 的两张底牌和三张翻牌,判断在所有可能的剩余两张公共牌及所有可能的对手底牌组合下,Wolf Chicken 是否必定获胜。若是,输出 "allin";否则输出 "check"。

思路:

这道题主要是分类讨论加模拟。
Wolf Chicken 的牌是固定的,所以只要对每种牌型进行分类讨论即可。
由于对面有 \(4\) 张未知牌,不难证明对面的牌型至少为同花顺。皇家同花顺也是同花顺。我们只需考虑 Wolf Chicken 的牌型为同花顺的情况即可。
首先判断出 Wolf Chicken 是哪个同花顺,然后枚举比他大的同花顺,判断对面是否能组出即可。

代码

点击查看代码
string a[N],b[N];


int f(string s){
	if(s[0]<='9'&&s[0]>='2'){
		return s[0]-'0';
	}else{
		if(s[0]=='A'){
			return 14;
		}else if(s[0]=='T'){
			return 10;
		}else if(s[0]=='J'){
			return 11;
		}else if(s[0]=='Q'){
			return 12;
		}else if(s[0]=='K'){
			return 13;
		}
	}
}

bool cmp(string x,string y){
	return f(x)<f(y);
}
string str="0123456789TJQKA";

void solve() {
	for(int i=1;i<=5;i++){
		cin>>a[i];
		b[i]=a[i];
	}
	for(int i=1;i<=4;i++){
		if(a[i][1]!=a[i+1][1]){
			cout<<"check\n";
			return;
		}
	}
	sort(a+1,a+1+5,cmp);
//	for(int i=1;i<=5;i++){
//		cout<<a[i]<<' ';
//	}cout<<endl;
	int st=f(a[1]);
	int flag=1;
	for(int i=2;i<=5;i++){
		if(f(a[i])==st+i-1){
			
		}else{
			flag=0;
		}
	}
	if(flag){
		int fl=0;
		for(int i=st+1;i<=10;i++){
			int f1=0,f2=1;
			if(f(b[1])>=i&&f(b[1])<=i+4){
				f2=0;
			}
			if(f(b[2])>=i&&f(b[2])<=i+4){
				f2=0;
			}
			if(f(b[3])>=i&&f(b[3])<=i+4){
				f1=1;
			}
			if(f(b[4])>=i&&f(b[4])<=i+4){
				f1=1;
			}
			if(f(b[5])>=i&&f(b[5])<=i+4){
				f1=1;
			}
			if(f1&&f2){
				fl=1;
				break;
			}
		}
		if(fl){
			cout<<"check\n";
		}else{
			cout<<"allin\n";
		}
		return;
	}
	if(st==2){
		if(f(a[2])==3&&f(a[3])==4&&f(a[4])==5&&f(a[5])==14){
			st=1;
			int fl=0;
			for(int i=st+1;i<=10;i++){
				int f1=0,f2=1;
				if(f(b[1])>=i&&f(b[1])<=i+4){
					f2=0;
				}
				if(f(b[2])>=i&&f(b[2])<=i+4){
					f2=0;
				}
				if(f(b[3])>=i&&f(b[3])<=i+4){
					f1=1;
				}
				if(f(b[4])>=i&&f(b[4])<=i+4){
					f1=1;
				}
				if(f(b[5])>=i&&f(b[5])<=i+4){
					f1=1;
				}
				if(f1&&f2){
					fl=1;
					break;
				}
			}
			if(fl){
				cout<<"check\n";
			}else{
				cout<<"allin\n";
			}
			return;
		}
	}
	
	cout<<"check\n";
}

B. Rectangle Flip 2

题意:

给定 \(n×m\) 的棋盘,每秒会有一个格子破裂(所有格子都会破裂一次),需依次输出前 \(i\) 个格子破裂后,棋盘上所有格子均完好的矩形数量(共输出 \(n×m\) 行)。

思路:

每破裂一个格子,就枚举仅包含这一个破裂格子的矩形,将其减去。对每个格子维护上方和下发最近的格子,然后对当前破裂的格子往左右枚举,直到枚举到同行的最近的左右两个破裂的格子或边界,按此方法计数,计数完更新维护信息,时间复杂度为 \(O(nm^2)\)

代码

点击查看代码
int a[505][505],b[505][505];
int A[505][505];
void solve() {
	int n,m;
	cin>>n>>m;
	for(int i=1;i<=n;i++){
		for(int j=1;j<=m;j++){
			b[i][j]=n+1;
		}
	}
	int s=n*(n+1)/2*m*(m+1)/2;
	for(int o=1;o<=n*m;o++){
		int x,y;
		cin>>x>>y;
		int LU=0,LD=n+1;
		for(int i=y;i>=1;i--){
			if(A[x][i])break;
			LU=max(a[x][i],LU);
			LD=min(b[x][i],LD);
			int RU=0,RD=n+1;
			for(int j=y;j<=m;j++){
				if(A[x][j])break;
				RU=max(a[x][j],RU);
				RD=min(b[x][j],RD);
				int U=max(LU,RU);
				int D=min(LD,RD);
//				cout<<i<<' '<<j<<' '<<U<<' '<<D<<endl;
				s-=(x-U)*(D-x);
			}
		}
		cout<<s<<endl;
		for(int i=1;i<=x;i++){
			b[i][y]=min(b[i][y],x);
		}
		for(int i=x;i<=n;i++){
			a[i][y]=max(a[i][y],x);
		}
		A[x][y]=1;
	}
}
posted @ 2026-01-25 18:53  ptlks  阅读(4)  评论(0)    收藏  举报