zoukankan      html  css  js  c++  java
  • AtCoder Grand Contest 038E

    (f Description)

    一个 (0)(n-1) 的随机数生成器,生成 (i) 的概率是 (A_i/S) ,其中 (S=sum_{i=0}^{n-1} A_i) ,请你求出每个数出现次数 (geq B_i) 的期望次数。

    (f Solution)

    什么生成函数爆推的做法一点不会啊……

    min-max容斥,考虑每个集合最早出现出现次数 (geq B_i) 的数的期望时间,由期望可加性,就是所有数 (<B_i) 的局面的期望出现次数之和。

    对于一个集合,下一步跳出它的概率 (P=frac{s}{S})(s) 是集合中的 (A_i) 之和。如果我们知道它出现的概率是 (p) ,那么它存在的期望次数就是 (frac{p}{P})

    然后考虑一下 (p) 这个东西怎么算,假如现在已经生成的数的概率为 (t_1)(t_m) ,个数是 (x_1)(x_m) ,且设 (X) 为总和,那么可得(对这个柿子还是有点困惑啊……懂,但是自己推就是错的,很自闭)

    [p=X! prod_{i=1}^{m} left( frac{t_i}{s} ight)^{x_i} frac{1}{x_i!} =frac{X!}{s^X} prod_{i=1}^m frac{t_i^{x_i}}{x_i!} ]

    (f_{i,j,k}) 表示前 (i) 个数,(X=j)(s=k) 的贡献(所谓的贡献,是容斥之后的贡献,并且dp的时候只算 (prod) 后面那一部分),然后背包一下就好了。

    然后我开始写,然后我又算不清复杂度了……为什么最近老这样……

    有个坑是当前这个数就算是0个,那也和不在集合是不一样的……然后我还把 (frac{1}{P}) 弄成 (P) 了……

    由于太懒了,所以就很不优雅地for到400了……

    #include<bits/stdc++.h>
    #define ll long long
    #define fr(i,x,y) for(int i=(x);i<=(y);i++)
    #define rf(i,x,y) for(int i=(x);i>=(y);i--)
    #define frl(i,x,y) for(int i=(x);i<(y);i++)
    using namespace std;
    const int N=404;
    const int p=998244353;
    int n,a[N],b[N];
    ll f[N][N];
    
    void read(int &x){ scanf("%d",&x); }
    
    ll qpow(ll sum,ll n){
    	ll ans=1;
    	for(;n;n>>=1,sum=sum*sum%p) if (n&1) ans=ans*sum%p;
    	return ans;
    }
    
    ll mul[N],inv[N];
    void init(){
    	mul[0]=1;
    	frl(i,1,N) mul[i]=mul[i-1]*i%p;
    	inv[N-1]=qpow(mul[N-1],p-2);
    	rf(i,N-2,0) inv[i]=inv[i+1]*(i+1)%p;
    }
    
    void Add(ll &x,ll y){
    	x+=y;//x%=p;
    	if (x<0) x+=p;
    	if (x>=p) x-=p;
    }
    
    int main(){
    	init();
    	read(n);
    	fr(i,1,n) read(a[i]),read(b[i]);
    	int S=0;
    	fr(i,1,n) S+=a[i];
    	//S=qpow(S,p-2);
    	f[0][0]=p-1;
    	fr(i,1,n)
    	 rf(k,400,0)
    	  fr(j,0,400)
    	   frl(x,0,b[i])
    		if (f[j][k]) Add(f[j+x][k+a[i]],p-f[j][k]*qpow(a[i],x)%p*inv[x]%p);
    	ll ans=0;
    	fr(j,0,400)
    	 fr(k,1,400)
    	  Add(ans,mul[j]*f[j][k]%p*qpow(k,p-1-j)%p*qpow(k,p-2)%p*S%p);
    	cout<<ans<<endl;
    	return 0;
    }
    
  • 相关阅读:
    [linux] 使用markdown写文档
    [c/c++] C数据结构: 链表 Linked List
    Apache 2 : starting apache
    GNU/CPIO 学习小结
    lsof 命令小结
    在Linux中扩展磁盘容量(1)
    在linux中扩展磁盘容量(2)LVM
    RHEL6.0 QEMU/KVM 建立新的虚拟机之配置Birdged Networking
    NFS server down机或重启导致的NFS系统错误
    Build linux kernel Module
  • 原文地址:https://www.cnblogs.com/ymzqwq/p/agc038e.html
Copyright © 2011-2022 走看看