zoukankan      html  css  js  c++  java
  • CF1097F Alex and a TV Show

    CF1097F Alex and a TV Show

    题意

    维护n个初始为空的可重集,支持以下操作:

    1 x v:令集合x等于{v}

    2 x y z:令集合x等于集合y与z的并

    3 x y z:令集合x等于集合y与z的积,A*B = {gcd(a,b)aA,bB}

    4 x v:询问v在集合x中出现次数模2的结果

    权值小于7000,n<=1e6

    题解

    题目只关注每个数的出现次数

    而对于v在集合x中的出现次数,我们发现可以通过莫比乌斯反演变成一个有关x的约数的出现次数和莫比乌斯函数的式子

    而我们只关注答案的奇偶性,所以可以转换为2进制

    考虑对每个集合开个bitset,对每个集合存数x的约数出现次数

    此时对于操作3和4只需要xor和and

    对于操作1预处理即可

    代码如下:

    #include<bits/stdc++.h>
    
    #define LL long long
    
    using namespace std;
    
    inline LL read()
    {
        LL f = 1 , x = 0;
        char ch;
        do
        {
            ch = getchar();
            if(ch=='-') f=-1;
        } while(ch<'0'||ch>'9');
        do
        {
            x=(x<<3) + (x<<1) + ch - '0';
            ch = getchar();
        }while(ch>='0'&&ch<='9');
        return f*x;
    }
    
    const int MAXN = 7000 + 10;
    const int N = 100000 + 10;
    
    bool isprime[MAXN + 500];
    int mu[MAXN],prime[MAXN],tot;
    bitset<7010>a[N],b[MAXN],u[MAXN];
    
    inline void pre()
    {
        mu[1] = 1;
        for(int i=2;i<MAXN;i++)
        {
            if(!isprime[i])
            {
                prime[++tot] = i;
                mu[i] = -1;
            }
            for(int j=1;j<=tot&&i*prime[j]<MAXN;j++)
            {
                isprime[i*prime[j]] = 1;
                if(i%prime[j]==0)
                {
                    break;
                }
                mu[i*prime[j]] = -mu[i];
            }
        }
    }
    
    int n,q;
    
    int main()
    {
        pre();
    
        for(int i=1;i<MAXN;i++)
        {
            for(int j=1;i*j<MAXN;j++)
            {
                b[i*j][i] = 1;
                u[i][i*j] = abs(mu[j]);
            }
        }    
        n = read(),q = read();
        for(int i=1;i<=q;i++)
        {
            int opt = read();
            if(opt==1)
            {
                int x = read(),v = read();
                a[x] = b[v];
            }
            if(opt==2)
            {
                int x = read(),y = read(),z = read();
                a[x] = a[y] ^a[z];
            }
            if(opt == 3)
            {
                int x = read(),y = read(),z = read();
                a[x] = a[y] & a[z];
            }
            if(opt == 4)
            {
                int x = read(),v = read();
                printf("%d",(a[x]&u[v]).count()&1);
            }
        }
    }

     

  • 相关阅读:
    一个int类型究竟占多少个字节
    TCMalloc 安装与使用
    [创意标题] spoj 11354 Amusing numbers
    如何更好地理解和使用Github
    一天JavaScript示例-点击图片显示大图片添加鼠标
    php方法综述除去换行符(PHP_EOL使用变量)
    使用jQuery和css3实现了仿淘宝ued博客左边的菜单切换动画
    【软件使用技巧】PL/SQL Developer实现双击table询
    newlisp 接受jenkins带空格的参数
    Oracle listener lsnrctl
  • 原文地址:https://www.cnblogs.com/wlzs1432/p/12073998.html
Copyright © 2011-2022 走看看