• 题解 luogu P3715 [HAOI2015]按位或


    传送门


    【分析】

    由拓展 min-max 容斥得:(displaystyle ext{k-thmax}(S)=sum_{Tsubseteq S}(-1)^{|T|-k}inom {|T|-1}{k-1}min(S))

    故本题认为 (max(S)) 表示选择若干个数字或起来后,数字 (S) 的最后一位出现时间的随机变量

    同理,(min(S)) 表示选择若干个数字或起来后,数字 (S) 的第一位出现时间的随机变量

    (displaystyle E(max(S))=sum_{varnothingsubset Tsubseteq S}(-1)^{|T|-1}E(min(S)))

    (P(min(S)=k)) 表明前 ((k-1)) 次选择的数字都与 (S) 不交,且第 (k) 次的有交

    (egin{aligned} herefore P(min(S)=k)&=(sum_{Tcap S=varnothing} p_T)^{k-1}cdot (sum_{Tcap S eqvarnothing} p_T) \&=(sum_{Tcap S=varnothing} p_T)^{k-1}cdot (1-sum_{Tcap S=varnothing} p_T) \&=(sum_{Tcup ar S=ar S} p_T)^{k-1}cdot (sum_{Tcup ar S=ar S} p_T) end{aligned})

    (displaystyle sum_{Tcup S=S} p_T) 即是对 ({p_T}) 进行高维前缀和后的结果 ({hat p_T})

    因此 (P(min(S)=k)=hat p_{ar S}^{k-1}cdot (1-hat p_{ar S}))

    (egin{aligned} herefore E(min(S)=k)&=sum_{k=1}^{infty} khat p_{ar S}^{k-1}cdot (1-hat p_{ar S}) \&=(1-hat p_{ar S})cdot [{ ext dover ext dx}(sum_{k=1}^infty x^k)]_{x=1-hat p_{ar S}} \&=(1-hat p_{ar S})cdot [{ ext dover ext dx}({1over 1-x})]_{x=1-hat p_{ar S}} \&=(1-hat p_{ar S})cdot [{1over (1-x)^2}]_{x=1-hat p_{ar S}} \&={1over 1-hat p_{ar S}} end{aligned})

    跑完 FWT 之后直接按上面公式枚举即可


    【代码】

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    typedef pair<ll, ll> pii;
    typedef double db;
    #define fi first
    #define se second
    
    inline int sgn(db x) { return (x>1e-6)-(x<-1e-6); }
    
    template<class T>
    void FWT(T *a, int len, int o=1) {
        T x, y;
        for(int k=0; 1<<k<len; ++k) for(int i=0, j;i<len;++i) if(~i>>k&1) {
            j=i^(1<<k);
            x=a[i], y=a[i]+a[j];
            if(o==-1) y=a[j]-a[i];
            a[i]=x, a[j]=y;
        }
    }
    
    int n;
    db p[1<<20];
    int main(){
        ios::sync_with_stdio(0);
        cin.tie(0); cout.tie(0);
        cin>>n;
        for(int i=0;i<1<<n;++i) cin>>p[i];
        FWT(p, 1<<n, 1);
    
        bool flag=0;
        db res=0;
        for(int i=1;i<1<<n;++i) 
            if( sgn(1-p[i^((1<<n)-1)])==0 ){
                flag=1;
                break;
            }
            else if(__builtin_popcount(i)&1) res+=1/(1-p[i^((1<<n)-1)]);
            else res-=1/(1-p[i^((1<<n)-1)]);
        if(flag) cout<<"INF";
        else cout<<fixed<<setprecision(9)<<res;
        cout.flush();
        return 0;
    }
    
  • 相关阅读:
    【Python】异常处理
    【Python】写入文件
    【Python】从文件中读取数据
    【Python】导入类
    【Python】继承
    【Python】使用类和实例
    SQL HAVING
    SQL GROUP BY
    SQL ORDER BY
    SQL CREATE INDEX
  • 原文地址:https://www.cnblogs.com/JustinRochester/p/15219394.html
Copyright © 2020-2023  润新知