把博客园图标替换成自己的图标
把博客园图标替换成自己的图标end

【CF1097F】Alex and a TV Show(bitset+莫反)

题目链接

  • \(n\) 个初始为空的可重集。
  • \(q\) 次操作,分为四种:
    • 将第 \(x\) 个集合赋值为 \(\{v\}\)
    • 令第 \(x\) 个集合为第 \(y\) 个集合与第 \(z\) 个集合的并。
    • 令第 \(x\) 个集合为第 \(y\) 个集合与第 \(z\) 个集合的积,定义 \(A*B=\{\gcd(a,b)|a\in A,b\in B\}\)
    • 询问 \(v\) 在第 \(x\) 个集合中出现次数的奇偶性。
  • \(1\le n\le10^5\)\(1\le q\le10^6\)\(1\le v\le 7000\)

维护约数出现次数

注意到这里集合的积定义比较奇怪,如果只是单纯维护原集合似乎不是很方便。

所以考虑直接维护每个约数的出现次数。

对于并,显然就是将约数出现次数直接相加。

对于积,容易发现就是将约数出现次数直接相乘。

然后对于 \(v\) 在第 \(x\) 个集合中的出现次数,列出式子:

\[\begin{aligned} \sum_{a\in S_x}[a=v]&=\sum_{a\in S_x}[v|a][\frac av=1]\\ &=\sum_{a\in S_x}[v|a]\sum_{d|\frac av}\mu(d)\\ &=\sum_{d=1}^{\lfloor\frac Vv\rfloor}\mu(d)\sum_{a\in S_x}[dv|a] \end{aligned} \]

发现 \(\sum\) 中的式子就是 \(dv\) 作为约数的出现次数,正好是我们维护的值。

bitset

本题一个特殊的地方就是只需要求奇偶性,所以考虑 bitset。

对于并,二进制下不进位相加显然就是异或。

对于积,相乘就是按位与。

而对于询问,我们对于 \(v\) 预处理一个 bitset,其中第 \(dv\) 位的值为 \(\mu(d)\operatorname{mod}2\)。那么这又是一个相乘的过程,只需要按位与即可。

代码:\(O(\frac{qv}{\omega})\)

#include<bits/stdc++.h>
#define Tp template<typename Ty>
#define Ts template<typename Ty,typename... Ar>
#define Rg register
#define RI Rg int
#define Cn const
#define CI Cn int&
#define I inline
#define W while
#define N 100000
#define V 7000
using namespace std;
namespace FastIO
{
	#define FS 100000
	#define tc() (FA==FB&&(FB=(FA=FI)+fread(FI,1,FS,stdin),FA==FB)?EOF:*FA++)
	char oc,FI[FS],*FA=FI,*FB=FI;
	Tp I void read(Ty& x) {x=0;W(!isdigit(oc=tc()));W(x=(x<<3)+(x<<1)+(oc&15),isdigit(oc=tc()));}
	Ts I void read(Ty& x,Ar&... y) {read(x),read(y...);}
}using namespace FastIO;
int n,Pt,P[V+5],Mu[V+5];bitset<V+5> a[N+5],v[N+5],g[N+5];
int main()
{
	RI Qt,i,j,op,x,y,z;read(n,Qt);
	for(Mu[1]=1,i=2;i<=V;++i) for(!P[i]&&(Mu[P[++Pt]=i]=-1),j=1;i*P[j]<=V;++j) if(P[i*P[j]]=1,i%P[j]) Mu[i*P[j]]=-Mu[i];else break;//线性筛
	for(i=1;i<=V;++i) for(j=i;j<=V;j+=i) v[j].set(i),Mu[j/i]&&(g[i].set(j),0);//预处理bitset
	W(Qt--) switch(read(op,x,y),op)
	{
		case 1:a[x]=v[y];break;case 2:read(z),a[x]=a[y]^a[z];break;case 3:read(z),a[x]=a[y]&a[z];break;//赋值;并;积
		case 4:putchar(48|(a[x]&g[y]).count()&1);break;//询问
	}return 0;
}
posted @ 2022-04-21 20:05  TheLostWeak  阅读(51)  评论(0编辑  收藏  举报