zoukankan      html  css  js  c++  java
  • 牛客 Wannafly 挑战赛26D 禁书目录 排列组合 概率期望

    原文链接https://www.cnblogs.com/zhouzhendong/p/9781060.html

    题目传送门 - NowCoder Wannafly 26D

    题意

      放一放这一题原先的题面:

    阿尔法城

    空间限制 512MB
    时间限制 2s

    题目描述

    听说遥远的α城里神仙题横行,毒瘤题占道,zzd 决定来送一道温暖。

    zzd 现在正距离α城很远处(可以理解成无穷远),通过望远镜看到了 α 城里的景象。

    α城中有 n 座高楼,排成一条直线,其中第 i 座高楼的高度为 a[i] ,颜色为 c[i] 。任意两个高楼不同,即使他们的高度和颜色都相同。

    zzd 惊喜地发现这些高楼排成的直线恰好与 zzd 的视线重合,且离 zzd 最近的是第 1 座高楼。

    如果一座大楼之前没有高度不小于它的高楼遮挡,那么 zzd 就能看见它。于是 zzd 很快就数出了他看到的颜色种数。

    α城里的神仙陈老爷想要阻止 zzd 送温暖,立马联合神仙 cly 发动了魔法:不断将高楼重新排列。

    这么多的变换,让 zzd 眼花缭乱。于是,zzd 决定,在去找 Mangoyang 并对陈老爷实施 α 行动之前,先问问你:对于所有排列,zzd 看到的颜色种数之和为多少?

    答案对 998244353 取模。

    输入描述

    第一行一个整数 n 。
    接下来 n 行,每行两个整数 a[i] 和 c[i] 。
    1<=n<=500000,
    1<=a[i],c[i]<=100000000

    输出描述

    一个整数,表示答案对 998244353 取模后的值。

    示例
    输入1
    4
    1 5
    4 3
    5 2
    3 1

    输出1
    50

    输入2
    10
    5 6
    1 2
    2 2
    10 9
    10 7
    8 6
    10 6
    1 2
    1 1
    8 3

    输出2
    6664320

      不过后来由于 ACM 赛制,样例 2 就没了。

    题解

      首先我们把这个总方案数转化成期望。

      根据期望的线性性,总答案可以分解成各个颜色被看见的概率之和。

      现在考虑如何求一个颜色被看见的概率。

      这里有一个结论——

    如果对于一个楼,高度不低于它的(包括它自己)有 $t$ 个,那么它被看见的概率就是 $frac 1t$ 。

      (证明:将当前楼插入比他高的楼的空隙中,有 $t$ 个方法,但是只有插在最前面的是能看见的)

      那么,一种颜色被看见的概率就是 $1-$ 每一个楼都没被看见的概率。注意到可能存在同种颜色有多个相同高度的楼的情况,需要将上面的结论升级一下——

    对于 $k$ 个相同高度的楼,如果高度不低于他们的楼有 $t$ 个,则他们中至少一个被看见的概率就是 $frac kt$ 

      (证明基于之前的结论,推导一下即可)

      于是就解决了这个问题。

      所以这个通过率是怎么回事……是不是都被某毒瘤出题人的 B 题拦住了?

    代码

    加了个hash表,成功把时限开到了标程4倍。

    #include <bits/stdc++.h>
    using namespace std;
    const int N=500005,mod=998244353;
    int Pow(int x,int y){
        int ans=1;
        for (;y;y>>=1,x=1LL*x*x%mod)
            if (y&1)
                ans=1LL*ans*x%mod;
        return ans;
    }
    int read(){
        int x=0;
        char ch=getchar();
        while (!isdigit(ch))
            ch=getchar();
        while (isdigit(ch))
            x=(x<<1)+(x<<3)+(ch^48),ch=getchar();
        return x;
    }
    int n,Fac[N],Inv[N],Ha[N],tax[N],hs=0,tot=0;
    struct Building{
        int a,c;
    }x[N];
    struct hash_map{
        static const int Ti=233,mod=1<<19;
        int cnt,k[mod+1],v[mod+1],nxt[mod+1],fst[mod+1];
        int Hash(int x){
            unsigned t=x;
            int v=(t<<3^t)&(mod-1);
            return v==0?mod:v;   
        }
        void clear(){
            cnt=0;
            memset(fst,0,sizeof fst);
        }
        void update(int x,int a){
            int y=Hash(x);
            for (int p=fst[y];p;p=nxt[p])
                if (k[p]==x){
                    v[p]=a;
                    return;
                }
            k[++cnt]=x,nxt[cnt]=fst[y],fst[y]=cnt,v[cnt]=a;
            return;
        }
        int find(int x){
            int y=Hash(x);
            for (int p=fst[y];p;p=nxt[p])
                if (k[p]==x)
                    return v[p];
            return 0;
        }
        int &operator [] (int x){
            int y=Hash(x);
            for (int p=fst[y];p;p=nxt[p])
                if (k[p]==x)
                    return v[p];
            k[++cnt]=x,nxt[cnt]=fst[y],fst[y]=cnt;
            return v[cnt]=0;
        }
    }Map;
    vector <int> v[N];
    int main(){
    //freopen("city9.in","r",stdin);
    //freopen("city9.out","w",stdout);
    //int st=clock();
        n=read();
        for (int i=Fac[0]=1;i<=n;i++){
            Fac[i]=1LL*Fac[i-1]*i%mod;
            v[i].clear();
        }
        Inv[n]=Pow(Fac[n],mod-2);
        for (int i=n;i>=1;i--)
            Inv[i-1]=1LL*Inv[i]*i%mod;
        for (int i=1;i<=n;i++)
            Inv[i]=1LL*Inv[i]*Fac[i-1]%mod;
        Map.clear();
        for (int i=1;i<=n;i++){
            x[i].a=read(),x[i].c=read();
            if (!Map[x[i].c])
                Map[x[i].c]=++tot;
            x[i].c=Map[x[i].c];
            Ha[++hs]=x[i].a;
        }
        sort(Ha+1,Ha+hs+1);
        hs=unique(Ha+1,Ha+hs+1)-Ha-1;
        memset(tax,0,sizeof tax);
        for (int i=1;i<=n;i++){
            x[i].a=lower_bound(Ha+1,Ha+hs+1,x[i].a)-Ha;
            tax[x[i].a]++;
            v[x[i].c].push_back(x[i].a);
        }
        for (int i=hs;i>=1;i--)
            tax[i]+=tax[i+1];
        int ans=0;
        for (int i=1;i<=tot;i++){
            vector <int> &a=v[i];
            sort(a.begin(),a.end());
            a.push_back(a.back()+1);
            int h=a[0],cnt=1,now=1;
            for (int j=1;j<a.size();j++){
                if (a[j]!=a[j-1]){
                    int t=tax[a[j-1]];
                    now=1LL*now*(mod+1-1LL*cnt*Inv[t]%mod)%mod;
                    cnt=0;
                }
                cnt++;
            }
            ans=(ans+mod+1-now)%mod;
        }
        ans=1LL*ans*Fac[n]%mod;
        printf("%d",ans);
    //cerr << "user time = " << clock()-st << endl;
        return 0;
    }
    

      

    数据生成器

    里面有参数自行调整。

    #include <bits/stdc++.h>
    using namespace std;
    typedef unsigned uint;
    const int N=1000005;
    int n=500000,m=1000,A[N],C[N];
    int Rand(int n){
    	uint a=rand(),b=rand();
    	return (a<<16|b)%n;
    }
    int main(){
    	srand(time(NULL));
    	freopen("city9.in","w",stdout);
    	printf("%d
    ",n);
    	A[0]=C[0]=1;
    	for (int i=1;i<=n;i++){
    		int a,c;
    		int p1=Rand(20),p2=Rand(20);
    		if (p1)
    			a=Rand(m)+1;
    		else
    			a=A[Rand(i)];
    		if (p2)
    			c=Rand(m)+1;
    		else
    			c=C[Rand(i)];
    		printf("%d %d
    ",A[i]=a,C[i]=c);
    	}
    	return 0;
    }
    

      

  • 相关阅读:
    ASP.NET MVC 几种 Filter 的执行过程源码解析
    C#中的线程二(BeginInvoke和Invoke)
    C#中的线程一(委托中的异步)
    C#比较dynamic和Dictionary性能
    C#微信公众平台开发—高级群发接口
    js 关闭浏览器
    切图神器 --- Assistor
    切图 -- cutterman
    mac上用teamviewer远程windows输入问题
    A quick introduction to HTML
  • 原文地址:https://www.cnblogs.com/zhouzhendong/p/NowCoder-Wannafly26D.html
Copyright © 2011-2022 走看看