[OIFC2025.10.13-10.19模拟三]1. 币硬翻题解

题目ID:23015必做题文件操作100分

最新提交:

Hidden

历史最高:

Hidden

时间限制: 1500ms

空间限制: 524288kB

输入文件名: coin.in

输出文件名: coin.out

题目描述

小 Y 现在正在模拟赛,但是一题不会。事已至此,他拿出了祖传棋盘。
这是一个 n×nn×n 的棋盘,每个格子上都有一个硬币,每个硬币只能是正或反。每次操作选择一个位置 (i,j)(i,j),然后将与这枚硬币在同一行或同一列的硬币全部翻面,需要注意的是,选择的这枚硬币不会翻面
小 Y 很快将所有硬币翻成了正面,作为他的同桌,你自然不能落下。小 Y 会告诉你初始时棋盘上反面朝上的 kk 枚硬币的位置。你希望求出将所有硬币翻成正面朝上的最小操作次数来薄纱小 Y。不过小 Y 的记性并不是很好,所以他给出的局面可能无解,如果无解,请告诉他 No Solution!

输入格式

第一行一个正整数 TT 表示数据组数。
对于每一组数据。
第一行两个正整数 n,kn,k 含义同题目描述。
接下来 kk 行,每行两个正整数 xi,yixi​,yi​,表示反面朝上的硬币的位置。

输出格式

对于每一组数据,输出一行。
若有解,输出最小操作次数。若无解,输出 No Solution!

样例

Input 1
 

1 3 4 1 1 2 1 3 2 3 3

Output 1
 

1

Input 2
 

1 5 10 5 3 5 5 3 3 3 5 4 3 4 5 1 3 1 5 2 3 2 5

Output 2
 

2

Input 3
 

1 5 16 4 2 1 1 2 1 5 3 4 3 5 4 2 2 4 1 3 5 1 3 1 2 1 4 2 3 5 5 5 2 4 4

Output 3
 

No Solution!

样例解释

对于样例一,操作 (3,1)(3,1) 即可。
对于样例二,先操作 (1,3)(1,3),再操作 (1,5)(1,5) 即可。

数据范围

对于 15%15% 的数据,2≤∑n≤102≤∑n≤10。
对于 40%40% 的数据,2≤∑n≤10002≤∑n≤1000。
对于另外 10%10% 的数据,保证有解。
对于 100%100% 的数据,2≤∑n≤105,1≤∑k≤min⁡{107,∑n2},1≤xi,yi≤n2≤∑n≤105,1≤∑k≤min{107,∑n2},1≤xi​,yi​≤n。
时空限制均为 std 两倍。
本题输入量较大,请注意代码常数。
这里给出快读模板。

 
template<class T> inline void read(T &n) {
	n = 0;
	char c = getchar();
	
	while(c < '0' || '9' < c) {
		c = getchar();
	}
	
	while('0' <= c && c <= '9') {
		n = n * 10 + c - '0';
		c = getchar();
	}
}

附件

sample.zip

思路

首先,注意到操作可以看成对行或列的+1操作,每次给一行或一列+1,要求最后得到黑点上数为奇数,白点上为偶数,且行和列次数相同。

因为涂两次效果一样,且为了行和列次数相同,所以最多只有一个序列存在大于 1 的数。

考虑位置 (x,y) 如果是 1,那么第x行的次数与第y列的次数的奇偶性不同,而0就代表奇偶性相同。

于是找到第一行,将其列记录奇偶性,再找到第一列,将其行记录奇偶性,然后,对于所有点,判断有无解。

若无解,输出No Solution!,有解输出答案即可。

代码见下

#include<bits/stdc++.h>
using namespace std;
long long t,n,k,h[100005],lt[100005],q[100005],w[100005],q2[100005],w2[100005],lk,kl,sd=0,fk=0;
struct one{
    long long x,y;
}a[10000007];
inline long long read(){
    long long x=0,f=1ll;
    char ch=getchar();
    while(ch<48||ch>57){
        ch=getchar();
    }
    while(ch>=48&&ch<=57){
        x=x*10+ch-48;
        ch=getchar();
    }
   	return x*f;
}
int main(){
    freopen("coin.in","r",stdin);
    freopen("coin.out","w",stdout);
    cin>>t;
    while(t--){
        cin>>n>>k;
        for(int i=1;i<=n;i++){
            h[i]=lt[i]=0;
            q[i]=q2[i]=w[i]=w2[i]=0;
        }
        fk=0;
        for(int i=1;i<=k;i++){
            a[i].x=read();
            a[i].y=read();
            h[a[i].x]++;
            lt[a[i].y]++;
            if(a[i].x==1){
                q[a[i].y]++;
            }
            if(a[i].x==n){
                q2[a[i].y]++;
            }
            if(a[i].y==1){
                w[a[i].x]++;
            }
            if(a[i].y==n){
                w2[a[i].x]++;
            }
            if(a[i].x==1&&a[i].y==1){
                fk=1;
            }
        }
        sd=0;
        for(int i=1;i<=k;i++){
            if(((q[a[i].y]>=1&&w[a[i].x]>=1)||(q[a[i].y]==0&&w[a[i].x]==0))&&fk==1){
                //sd=1;
            }
            else if(((q[a[i].y]>=1&&w[a[i].x]==0)||(q[a[i].y]==0&&w[a[i].x]>=1))&&fk==0){
                //sd=1;
            }
            else{
            	sd=1;
			}
        }
        if(sd==1){
            cout<<"No Solution!"<<endl;
        }
        else{
            lk=0;
            kl=0;
            for(int i=1;i<=n;i++){
                if(q[i]>=1){
                    lk++;
                }
                if(w[i]>=1&&fk==0){
                    kl++;
                }       
                if(w[i]==0&&fk==1){
                    kl++;
                }   
            }
            cout<<min(max(lk,kl),max(n-lk,n-kl))<<endl;             
        }
    }
    return 0;
}

posted @ 2025-10-18 10:24  bz02_2023f2  阅读(9)  评论(0)    收藏  举报  来源