• BZOJ4036 按位或


    解:有两种做法......

    第一种,按照秘密袭击coat的套路,我们只需要求出即可。因为一种操作了i次的方案会被恰好计数i次。

    那么这个东西怎么求呢?直接用FWT的思想,对于一个状态s,求出选择s所有子集的概率ps。那么第i次操作后是s的子集的概率就是psi

    设fs表示第i次操作之后是s的子集的概率。

    把所有的f求出来之后做一次IFWT即可。然后我们对于所有非全集求和。

    参考资料

     1 #include <bits/stdc++.h>
     2 
     3 const int N = 30, M = 1500010;
     4 const double eps = 1e-12;
     5 
     6 double f[M], p[M], w[M];
     7 int cnt[M], pw[M], n, lm;
     8 
     9 inline void FWT_or(double *a, int n, int f) {
    10     for(int len = 1; len < n; len <<= 1) {
    11         for(int i = 0; i < n; i += (len << 1)) {
    12             for(int j = 0; j < len; j++) {
    13                 a[i + len + j] += f * a[i + j];
    14             }
    15         }
    16     }
    17     return;
    18 }
    19 
    20 int main() {
    21     scanf("%d", &n);
    22     lm = 1 << n;
    23     for(int i = 0; i < lm; i++) {
    24         scanf("%lf", &p[i]);
    25         w[i] = p[i];
    26         if(i) {
    27             cnt[i] = 1 + cnt[i - (i & (-i))];
    28         }
    29         if(i > 1) {
    30             pw[i] = pw[i >> 1] + 1;
    31         }
    32     }
    33     FWT_or(p, lm, 1);
    34     for(int i = 0; i < lm; i++) {
    35         if(i != lm - 1 && p[i] > 1 - eps) {
    36             puts("INF");
    37             return 0;
    38         }
    39         f[i] = 1.0 / (1 - p[i]);
    40     }
    41     FWT_or(f, lm, -1);
    42     double ans = 0;
    43     for(int i = 0; i < lm - 1; i++) {
    44         ans += f[i];
    45     }
    46     printf("%.10f
    ", ans);
    47     return 0;
    48 }
    AC代码

    第二种:Min-Max容斥。

    设fs为把状态s的所有元素中至少一个变成1的期望次数。

    同样是对步数0~∞求和,每次的概率是(没选到)i。最后Min-Max容斥统计答案。

     1 #include <bits/stdc++.h>
     2 
     3 const int N = 30, M = 1500010;
     4 const double eps = 1e-12;
     5 
     6 double f[M], p[M], w[M];
     7 int cnt[M], pw[M], n, lm;
     8 
     9 inline void FWT_or(double *a, int n, int f) {
    10     for(int len = 1; len < n; len <<= 1) {
    11         for(int i = 0; i < n; i += (len << 1)) {
    12             for(int j = 0; j < len; j++) {
    13                 a[i + len + j] += f * a[i + j];
    14             }
    15         }
    16     }
    17     return;
    18 }
    19 /*
    20 2
    21 0.25 0.25 0.25 0.25
    22 
    23 */
    24 int main() {
    25     scanf("%d", &n);
    26     lm = 1 << n;
    27     for(int i = 0; i < lm; i++) {
    28         scanf("%lf", &p[i]);
    29         w[i] = p[i];
    30         if(i) {
    31             cnt[i] = 1 + cnt[i - (i & (-i))];
    32         }
    33         if(i > 1) {
    34             pw[i] = pw[i >> 1] + 1;
    35         }
    36     }
    37     FWT_or(p, lm, 1);
    38     for(int i = 0; i < lm; i++) {
    39         if(i != lm - 1 && p[i] > 1 - eps) {
    40             printf("INF
    ");
    41             return 0;
    42         }
    43         //printf("p %d = %lf 
    ", i, p[i]);
    44         f[i] = 1.0 / (1 - p[(lm - 1) ^ i]);
    45     }
    46     //FWT_or(f, lm, -1);
    47     double ans = 0;
    48     for(int i = 1; i < lm; i++) {
    49         if(cnt[i] & 1) ans += f[i];
    50         else ans -= f[i];
    51     }
    52     printf("%.10f
    ", ans);
    53     return 0;
    54 }
    AC代码
  • 相关阅读:
    git 一般的使用操作
    php 导出excel,csv
    安装sublime_text_3
    安装mongodb记录,mongo基本命令记录
    redis 安装记录
    YII2 activeform样式修改
    go 安装下载
    java.lang.RuntimeException: Unable to start activity ComponentInfo{com.hbsjz/com.hbsjz.BaseMapActivity}:
    SQLServer创建触发器,更新表
    SQL Server触发器创建、删除、修改、查看示例步骤
  • 原文地址:https://www.cnblogs.com/huyufeifei/p/10721835.html
Copyright © 2020-2023  润新知