题解:CF1909E Multiple Lamps
CF1909E 题解
题面
思路
首先,我们考虑一个灯最后亮着的条件是什么。对于一个灯的编号为
于是很自然的想到一个很经典的结论:当且仅当一个数为完全平方数时,其因子个数为奇数。
于是就可以考虑把所有的灯都开起来,最终剩下亮着的必然是编号为完全平方数的灯,而个数是
继续考虑可以发现,当
对于
代码
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<vector>
#define ll long long
using namespace std;
const int MN=200005;
ll T,n,m,u[MN],v[MN];
vector<ll>ans[20];
void write(ll n){if(n>9)write(n/10);putchar(n%10+'0');}
ll read(){ll x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}return x*f;}
ll gs(ll x){ll res=0;while(x){x&=(x-1);/*移除最后一个1*/res++;}return res;}//计算二进制中1的个数
void solve(){
for(ll i=0; i<ans[n].size(); i++){//枚举所有按灯情况
bool flag=false;
for(ll j=1; j<=m; j++) if(ans[n][i]>>(u[j]-1)&1&&!(ans[n][i]>>(v[j]-1)&1)){//判断是否满足给的要求
flag=true;//不满足就直接结束
break;
}
if(!flag){//满足条件
write(gs(ans[n][i]));putchar('\n');
for(ll j=1; j<=n; j++) if(ans[n][i]>>(j-1)&1) write(j),putchar(' ');
putchar('\n');return;
}
}
printf("-1\n");
}
int main(){
for(ll i=5; i<=19; i++)/*枚举位数*/for(ll s=1; s<(1<<i); s++){//因为必须至少亮一盏灯,所以枚举的状态从1开始,注意这里的状态不是灯的,而是按灯的状态。
ll num=0;//记录按灯之后灯的状态
for(ll j=1; j<=i; j++) if((s>>(j-1))&1)/*第j盏灯是亮的,因为s是从第0位开始的,所以用j-1*/for(ll k=j; k<=i; k+=j) num^=(1<<(k-1));//k-1同前
if(gs(num)<=i/5) ans[i].push_back(s);//这是一种合法的情况
}
T=read();while(T--){//多组数据
n=read();m=read();
for(int i=1; i<=m; i++) u[i]=read(),v[i]=read();
if(n<=4){printf("-1\n");continue;}//无解情况直接输出-1
if(n>=20){//保证有解,输出把所有灯都点亮的方案
write(n);putchar('\n');//输出方案个数
for(ll i=1; i<=n; i++) write(i),putchar(' ');//每个灯都点亮
putchar('\n');continue;
}
solve();
}
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 单元测试从入门到精通
· 上周热点回顾(3.3-3.9)
· winform 绘制太阳,地球,月球 运作规律