专栏文章
P11613 题解
P11613题解参与者 1已保存评论 0
文章操作
快速查看文章及其快照的属性,并进行相关操作。
- 当前评论
- 0 条
- 当前快照
- 1 份
- 快照标识符
- @mimz29x4
- 此快照首次捕获于
- 2025/12/01 17:54 3 个月前
- 此快照最后确认于
- 2025/12/01 17:54 3 个月前
首先转成最大独立集,对图 计数有经典做法,取出前两个点,如果这两个点邻域不同则交换之,得到一个相等的图。
因此这两个点邻域相同,讨论两点间是否有边,如果有边那么两个点至多选一个,看成删除一个点,否则必定同时选或不选,生成一个大小为 的点。
那么不断合并大小相同的两个点,最终图上会剩若干大小不同的点,设为 。
很显然我们的策略就是按 从大到小贪心,每个点如果邻域没选就选上。
那么记 ,先考虑 个点得到 个这样的组的方案数 。
记 ,考虑加入最后一个点时 的变化过程,首先必定存在 并且不断选择合成才能不生成 的点,而生成出 后,如果原来不存在 ,那么合成过程停止;否则如果把两个 合成就不存在大小为 的点了,所以原本有 的情况下会删除一个 的点。
那么 。
然后考虑 向某个 转移的方案数,考虑方案数,如果有一个 ,则 的点可以任意选择是否与 连边。
所以 时必定有偶数种连边方案,所以 只能向 转移答案。
时间复杂度 。
代码:
CPP#include<bits/stdc++.h>
using namespace std;
const int MAXN=1<<14|5;
bitset <MAXN> f,g,h,z;
vector <array<int,2>> qy[MAXN];
int n,q;
signed main() {
ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
cin>>q;
for(int i=1,x,y;i<=q;++i) cin>>x>>y,n=max(n,x),qy[x].push_back({x-y,i});
f[0]=1;
for(int i=1;i<=n;++i) {
h.reset(),g.reset();
for(int x=1;x<=i;++x) {
h[x]=f[x-1]^f[x+(x&-x)-1];
if(h[x]) g.flip(x),g.flip(x&(x-1));
}
f=h;
for(auto o:qy[i]) z[o[1]]=g[o[0]];
}
for(int i=1;i<=q;++i) cout<<z[i]<<"\n";
return 0;
}
相关推荐
评论
共 0 条评论,欢迎与作者交流。
正在加载评论...