题目
n(n<=2e5)盏灯,编号1到n,一开始全是熄灭的
n个开关,第i个控制着所有i的倍数,按下i的时候,i、2i、...这些灯的状态会被翻转,
m(m<=2e5)个限制,第j条限制形如uj,vj,表示uj这个开关按下之后,vj必须也按下,限制是单向的
找到一种按开关的方案,使得:
1. 至少按了一盏灯的开关
2. 总的亮灯盏数不超过n/5(下取整)个
输出按下的开关的总个数,以及具体按下的每个开关
实际t(t<=1e4)组样例,但保证sumn不超过2e5
思路来源
tourist代码
题解
观察性质可知,如果[1,n]的所有开关都按下,则最终亮灯的,
是因数个数为奇数个的数,即完全平方数,完全平方数个数为sqrt(n)个
而当n>=20时,sqrt(n)<=n/5成立,所以只需要关注n<20的情况
先打表预处理出来可能的集合,
leg[n](n<=20)表示最终亮灯盏数不超过n/5时所有可能的按开关的方式
由于亮灯盏数和按开关的方式是一一对应的(依次考虑亮灭及是否按),
所以,实际合法的状态不会超过,极限是
对于n<=20的询问,暴力遍历所有合法状态,依次判断每个约束是否成立即可
由于n<=20,可以用位运算记录一下每盏灯的亮灭及各个开关的选取情况
代码
// Problem: E. Multiple Lamps
// Contest: Codeforces - Pinely Round 3 (Div. 1 + Div. 2)
// URL: https://codeforces.com/contest/1909/problem/E
// Memory Limit: 256 MB
// Time Limit: 3000 ms
//
// Powered by CP Editor (https://cpeditor.org)
#include<bits/stdc++.h>
using namespace std;
#define rep(i,a,b) for(int i=(a);i<=(b);++i)
#define per(i,a,b) for(int i=(a);i>=(b);--i)
typedef long long ll;
typedef double db;
typedef pair<ll,int> P;
#define fi first
#define se second
#define pb push_back
#define dbg(x) cerr<<(#x)<<":"<<x<<" ";
#define dbg2(x) cerr<<(#x)<<":"<<x<<endl;
#define SZ(a) (int)(a.size())
#define sci(a) scanf("%d",&(a))
#define scll(a) scanf("%lld",&(a))
#define pt(a) printf("%d",a);
#define pte(a) printf("%d\n",a)
#define ptlle(a) printf("%lld\n",a)
#define debug(...) fprintf(stderr, __VA_ARGS__)
const int N=2e5+10,M=21;
int t,n,m,u[N],v[N],lg[1<<M],st,st2;
vector<int>leg[M];
void init(){
rep(i,1,(1<<M)-1){
lg[i]=lg[i>>1]+1;
}
rep(i,1,19){
int up=1<<i;
rep(j,1,up-1){
int vis=0;
rep(k,1,i){
if(j>>(k-1)&1){
for(int l=k;l<=i;l+=k){
vis^=(1<<l);
}
}
}
if(__builtin_popcount(vis)<=i/5){
leg[i].pb(j);
}
}
}
}
void sol(){
sci(n),sci(m);
rep(i,1,m){
sci(u[i]),sci(v[i]);
u[i]--,v[i]--;
}
if(n>=20){
printf("%d\n",n);
rep(i,1,n){
printf("%d%c",i," \n"[i==n]);
}
return;
}
for(auto w:leg[n]){
bool ok=1;
rep(i,1,m){
if(w>>u[i]&1 && !(w>>v[i]&1)){
ok=0;
break;
}
}
if(ok){
int sz=__builtin_popcount(w);
printf("%d\n",sz);
rep(j,0,sz-1){
printf("%d%c",lg[w&(-w)]," \n"[j==sz-1]);
w-=w&(-w);
}
return;
}
}
puts("-1");
}
int main(){
init();
//sieve();
sci(t); // t=1
while(t--){
sol();
}
return 0;
}