首页 > 其他分享 >[USACO2

[USACO2

时间:2024-09-27 20:00:42浏览次数:9  
标签:10 le 下此 int USACO2 按钮 操作

[USACO2.2] 派对灯 Party Lamps

题目描述

我们有 \(n\) 盏彩色灯,他们分别从 \(1 \sim n\) 被标上号码。这些灯都连接到四个按钮:

按钮 \(1\):当按下此按钮,将改变所有的灯:本来亮着的灯就熄灭,本来是关着的灯被点亮。

按钮 \(2\):当按下此按钮,将改变所有奇数号的灯。

按钮 \(3\):当按下此按钮,将改变所有偶数号的灯。

按钮 \(4\):当按下此按钮,将改变所有序号是 \(3k+1 \ (k \in [0,+\infty) \cap \mathbb Z)\) 的灯。例如:\(1,4,7,10 \dots\)

一个计数器 \(c\) 记录按钮被按下的次数。当宴会开始,所有的灯都亮着,此时计数器 \(c\) 为 \(0\)。

输出格式

第一行一个正整数 \(n\);第二行一个整数 \(c\),表示最后计数器的数值。

第三行若干个整数,表示最后亮着的灯,以 -1 结束。

第四行若干个整数,表示最后关着的灯,以 -1 结束。

输出格式

每一行是所有灯可能的最后状态(没有重复)。

每一行有 \(n\) 个字符,第 \(i\) 个字符表示 \(i\) 号灯。\(0\) 表示关闭,\(1\) 表示亮着。这些行必须从小到大排列(看作是二进制数)。

如果没有可能的状态,则输出一行 IMPOSSIBLE

对于 \(100\%\) 的数据,\(10 \le n \le 100\),\(0 \le c \le 10^4\)。

思路

我们发现 \(0 \le c \le 10^4\),如果我们直接深搜,则会发现复杂度飙升到 \(O(2^{10 ^ 4})\)。

我们手模几个操作,发现序列的最终结果跟操作的顺序没有关系,也就是说这几种操作满足交换律

我们还会发现,同一个操作操作两次相当于没有操作。

所以我们可以把 \(c \le 10 ^ 4\) 的操作变为 \(c \le 4\) 次的操作。

首先判断 \(c\) 的奇偶性,再使用状态压缩表示进行了哪几种操作,并且排除掉集中不符合设定的操作,对于每个可行的操作,我们存下答案,然后按照字典序排序即可。

\(code\)

#include<iostream>
#include<algorithm>
using namespace std;
const int MAXN = 105;
int n,c;
int judge[MAXN];
int x;
int ans[MAXN][20];
int anscnt = 0;
int pre[MAXN];
void make(int id){
	if(id == 1){
		for(int i = 1;i <= n;i++){
			pre[i] = pre[i] ^ 1;
		}
	}else if(id == 2){
		for(int i = 1;i <= n;i += 2){
			pre[i] = pre[i] ^ 1;
		}
	}else if(id == 3){
		for(int i = 2;i <= n;i += 2){
			pre[i] = pre[i] ^ 1;
		}
	}else{//id == 4
		for(int i = 1;i <= n;i += 3){
			pre[i] = pre[i] ^ 1;
		}
	}
}
string anss[MAXN];
int main(){
	scanf("%d%d", &n, &c);
	while(1){
		cin>>x;
		if(x == -1) break;
		judge[x] = 1;
	}
	while(1){
		cin>>x;
		if(x == -1) break;
		judge[x] = -1;
	}
	for(int sta = 0;sta <= 15;sta++){
		int cnt = 0;
		for(int i = 1;i <= n;i++) pre[i] = 1;
		for(int i = 0;i <= 3;i++){
			if(sta & (1 << i)) cnt++;
		}
		if((cnt % 2) != (c % 2)) continue;
		if(cnt > c) continue;
		for(int i = 0;i <= 3;i++){
			if(sta & (1 << i)){
				make(i);
			}
		}
		bool flag = true;
		for(int i = 1;i <= n;i++){
			if(judge[i] != 0){
				if(judge[i] == -1 && pre[i] == 1){
					flag = false;break;
				}
				if(judge[i] == 1 && pre[i] == 0){
					flag = false;break;
				}
			}
		}
		if(flag){
			anscnt++;
			for(int i = 1;i <= n;i++){
				ans[i][anscnt] = pre[i];
			}
		}
	}
	if(anscnt == 0) cout<<"IMPOSSIBLE";
	else{
		for(int i = 1;i <= anscnt;i++){
			for(int j = 1;j <= n;j++){
				anss[i].append(ans[j][i] == 1 ? "1" : "0");
			}
		}
		sort(anss + 1,anss + anscnt + 1);
		for(int i = 1;i <= anscnt;i++){
			cout<<anss[i]<<endl;
		}
	}
	return 0;
}

标签:10,le,下此,int,USACO2,按钮,操作
From: https://www.cnblogs.com/wyl123ly/p/18436467

相关文章

  • P8908 [USACO22DEC] Palindromes P 题解
    P8908[USACO22DEC]PalindromesP题解算是好题,虽然没什么人做(简单地,我们考虑如何将一个字符串改变为回文串。显然如果我们判定所有\(\texttt{G}\)组成的是回文串,那么整个串一定是回文的。于是我们只考虑改变\(\texttt{G}\)的位置。那么由这类题的套路不难知道最优的变换......
  • P8907 [USACO22DEC] Making Friends P 题解
    P8907[USACO22DEC]MakingFriendsP题解我们考虑维护每个\(i\),在\(i\)的后面有多少个点和它有朋友关系。初步的想法是每删掉一个人就给集合里所有的点连边。但是我们发现这样太不优了,有很多边会重复连很多次。优化的想法是对于\(i\),删去之后连的边就成了一个完全图,于是......
  • P8906 [USACO22DEC] Breakdown P 题解
    P8906[USACO22DEC]BreakdownP题解显然的套路是删边转化为加边。考虑到维护整条路径不好维护,于是考虑转化维护\(f_{i,k},g_{i,k}\)分别表示\(1,n\)到\(i\)走了\(k\)步时的最短路。那么此时\(k\le4\)。我们先考虑\(f\)的转移,\(g\)的转移是等价的。那么对于\((......
  • P8907 [USACO22DEC] Making Friends P
    题目思路我们可以统计出所有点对之间应该有的边的数量然后再减去之前的\(m\)。对于每个点维护一个集合,统计该点应该连接的点。对于每条初始边,我们将其看作从编号小的点连向编号大的点,并在编号小的集合中放入编号大的点。处理删除\(i\)点操作,答案加上目前集合\(i\)的大......
  • P9977[USACO23DEC]BovineAcrobaticsS
    https://www.luogu.com.cn/problem/P9977https://www.luogu.com.cn/article/ijti2qdg最后一段的理解,个人认为不妥,应该根据代码来看:#include<stdio.h>#include<algorithm>structnode{ inta,b;}c[200010];boolcmp(nodea,nodeb){ returna.b<b.b;}intans[......
  • 题解:P9938 [USACO21OPEN] Acowdemia II B
    首先根据每篇出版物构建一个资历比较矩阵\(g\),其中\(g_{a,b}=1\)表示研究员\(a\)比\(b\)资历更高。遍历每篇出版物,识别出第一个降序的名字,然后假定该名字之后的所有研究员资历都比当前名字对应的研究员资历高即可。代码:#include<bits/stdc++.h>usingnamespacestd;......
  • 题解:P9951 [USACO20FEB] Swapity Swap B
    奶牛的排列经过\(x\)次后会回到原来的位置,理解以下:\([a_1,a_2]\)的牛翻转两次就会回到原来的位置,\([b_1,b_2]\)的牛翻转两次也会回到原来的位置,所以原来奶牛的排列经过一定次数的旋转后一定会回到原来位置。我们只要先模拟得出多少次后第\(i\)位的奶牛会回到原来的位置,然后......
  • 题解:P9953 [USACO20OPEN] Social Distancing II B
    解决思路:根据奶牛的位置对数组进行排序。计算相邻健康奶牛和感染奶牛之间的最小距离。这个距离值减一用来估计感染传播的半径。(确保了感染奶牛之间的距离在当前半径下不会导致传播给其他健康奶牛。)遍历排序后的奶牛列表,找到每一段连续感染奶牛的区域,并计算这些区域中可能需要的......
  • 题解:P9957 [USACO20DEC] Stuck in a Rut B
    由于\(x,y\leq10^9\),我们无法模拟每个时间段。因此,我们需要尝试判断两头牛何时会相交。一个重要的观察是,牛不能后退,所以两头牛发生碰撞的唯一方式是\(n[x]>e[x]\)且\(n[y]<e[y]\)。可以按牛的起始坐标进行排序,然后模拟这些碰撞。代码:#include<bits/stdc++.h>using......
  • [USACO2.4] 两只塔姆沃斯牛 The Tamworth Two--记忆化题解
    题目复述:链接跳转:[USACO2.4]两只塔姆沃斯牛TheTamworthTwo-洛谷#[USACO2.4]两只塔姆沃斯牛TheTamworthTwo##题目描述两只牛逃跑到了森林里。FarmerJohn开始用他的专家技术追捕这两头牛。你的任务是模拟他们的行为(牛和John)。追击在$10\times10$的平面网......