zoukankan      html  css  js  c++  java
  • 简单子集运算

    参考


    对于集合 (U = {1,2,cdots,n}), 有下标系统 (A = {Xmid Xsubseteq U}),和定义在 (A) 上的函数:(f:A o mathcal R)(mathcal R) 大概是某个很牛逼的代数系统,有交换律什么的,应该直接默认是实数域就行了)

    本文讨论对于这个函数 (f) 的变换。

    用状压模拟 (f) 的下标系统:

    n = read();
    for (int I = 0; I < (1 << n); ++ i) f[i] = read();
    


    子集和

    [hat f(I) = sum_{Tsubseteq I} f(T) ]

    求这个 (hat f)

    从另一个角度看待 (f) 的状压表示, 二进制的每一位看成多维数组的一个维度的某个数,那么这个子集和就是个高维前缀和。

    插入

    高维前缀和的算法:

    对于一个高维点 ((x_1,x_2,cdots,x_n)), 其高维前缀和是对 ((y_1le x_1,y_2le x_2,cdots,y_nle x_n)) 这些点值的求和。

    将这些点值按照最后一维分类,将整个 n 维超立方体分成了 (|{kmid kle x_n}|) 个 n - 1 维的超立方体, 看上去就十分显然了。

    代码

    for (int i = 0; i < n; ++ i)
      for (int s = 0; s < (1 << n); ++ s)
        	if ((s >> i) & 1) f[s] += f[s ^ (1 << i)];
    

    子集和的逆变换

    就是给你 (hat f), 求 (f)

    有了前面的铺垫,这个东西就很简单了,就是对每一维从大到小扫过去差分,不过在这里一个维只有两个点值所以看起来就很简洁。

    代码

    for (int i = 0; i < n; ++ i)
      for (int s = 0; s < (1 << n); ++ i)
        if ((s >> i) & 1) f[s] -= f[s ^ (1 << i)];
    

    超集和

    [f(I)zeta = sum_{Isubseteq T} f(T) ]

    给 f 求 fζ。

    就是把 1 看成 0, 0 看成 1 了而已, 在一般的有限高维下标系统里, 可以直接看成把偏序关系反过来做子集和。

    代码

    for (int i = 0; i < n; ++ i)
      for (int s = 0; s < (1 << n); ++ s)
        	if (! ((s >> i) & 1)) f[s] += f[s ^ (1 << i)];
    

    超集和逆变换

    不多说了,代码

    for (int i = 0; i < n; ++ i)
      for (int s = 0; s < (1 << n); ++ s)
        	if (! ((s >> i) & 1)) f[s] -= f[s ^ (1 << i)];
    

    补集和

    这个东西是啥啊,原文没说我不知道。

  • 相关阅读:
    在Windows系统下搭建ELK日志分析平台
    ELK安装成windows服务
    ElasticSearch NEST笔记
    ElasticSearch5.0——IK词库加载
    ElasticSearch速学
    搜索引擎选择: Elasticsearch与Solr
    windows文件名太长无法删除的解决办法
    Elasticsearch(八)【NEST高级客户端--Mapping映射】
    elasticsearch 配置详解
    Elasticsearch(八)【NEST高级客户端--分析器】
  • 原文地址:https://www.cnblogs.com/tztqwq/p/14527528.html
Copyright © 2011-2022 走看看