CodeForces - 1097F Alex and a TV Show

题意:

给定 n n n 个空的 m u l t i s e t multiset multiset,有四种操作:① 1 , x , v 1, x, v 1,x,v,表示将第 x x x 个集合赋为 {   v   ~v~  v };② 2 , x , y , z 2, x, y, z 2,x,y,z,令 x = y ∪ z x = y \cup z x=yz;③ 3 , x , y , z 3, x, y, z 3,x,y,z,令 x = y   R   z x = y~R~z x=y R z R = { g c d ( a , b ) ∣ a ∈ y , b ∈ z } R=\{gcd(a,b)\mid a \in y, b \in z\} R={gcd(a,b)ay,bz};④ 4 , x , v 4, x, v 4,x,v,询问集合 x x x v v v 出现次数的奇偶性。 ( n ≤ 1 0 5 ,   q ≤ 1 0 6 ,   v ≤ 7000 ) (n\leq10^5,~q\leq10^6,~v\leq7000) (n105, q106, v7000)

链接:

https://codeforces.com/contest/1097/problem/F

解题思路:

只需要得到结果的奇偶性,使用 b i t s e t bitset bitset 操作。由于有 ③ 操作,涉及 g c d gcd gcd,即因子的操作, b s [ x ] [ i ] bs[x][i] bs[x][i] 中维护的是 i i i 作为 x x x 因子出现次数的奇偶性。预处理后,① 操作为赋值,② 操作为 b i t s e t bitset bitset 相异或,③ 操作 为 b i t s e t bitset bitset 相位与。
对于 ④ 操作:
f ( x ) f(x) f(x) = x x x 作为因子出现次数, g ( x ) g(x) g(x) = x x x 出现次数,
f ( n ) = ∑ n ∣ d g ( d ) f(n) = \sum\limits_{n|d}g(d) f(n)=ndg(d)
进而 g ( n ) = ∑ n ∣ d μ ( d n ) f ( d ) g(n) = \sum\limits_{n|d}\mu(\frac{d}{n})f(d) g(n)=ndμ(nd)f(d)
预处理出 μ ( x ) \mu(x) μ(x) 对应的 b i t s e t bitset bitset 即可。

参考代码:
#include<bits/stdc++.h>
 
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
#define sz(a) ((int)a.size())
#define pb push_back
#define lson (rt << 1)
#define rson (rt << 1 | 1)
#define gmid (l + r >> 1)
const int maxn = 1e5 + 5;
const int mod = 1e9 + 7;
const int inf = 0x3f3f3f3f;

bitset<7005> a[maxn], val[7005], msk[7005];
int mu[7005], vis[7005], prime[7005];
int n, q, tot;

void init(){

    mu[1] = 1, vis[1] = 1;
    for(int i = 2; i <= 7000; ++i){

        if(!vis[i]) prime[++tot] = i, mu[i] = -1;
        for(int j = 1; j <= tot && i * prime[j] <= 7000; ++j){

            vis[i * prime[j]] = 1;
            if(i % prime[j]) mu[i * prime[j]] = -mu[i];
            else { mu[i * prime[j]] = 0; break; }
        }
    }
    for(int i = 1; i <= 7000; ++i){

        for(int j = i; j <= 7000; j += i){

            val[j][i] = 1;
            if(mu[j / i]) msk[i][j] = 1;
        }
    }
}

int main(){
 
    ios::sync_with_stdio(0); cin.tie(0);
    init();
    cin >> n >> q;
    while(q--){

        int opt, x, y, z; cin >> opt >> x >> y;
        if(opt == 1){

            a[x] = val[y];
        }
        else if(opt == 2){

            cin >> z;
            a[x] = a[y] ^ a[z];
        }
        else if(opt == 3){

            cin >> z;
            a[x] = a[y] & a[z];
        }
        else{

            cout << ((a[x] & msk[y]).count() & 1);
        }
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值