[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();
}
}
附件
思路
首先,注意到操作可以看成对行或列的+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;
}

浙公网安备 33010602011771号