• 洛谷P5401 [CTS2019]珍珠(生成函数)


    洛谷P5401 [CTS2019]珍珠(生成函数)

    题目大意

    白云苍狗,沧海桑田。
    白云的眼前只剩下了模糊的一片。
    在若隐若现之中,它看到了一个个小小的珍珠,有一些发着五彩的光芒。这些珍珠是白兔留下来的,每颗珍珠有一个颜色,为 (D) 种颜色中随机的一种。
    白云想把这些珍珠放进一些小瓶子中,每个瓶子能恰好容纳两颗珍珠。不过它也有要求,每个瓶子必须装满,并且装的都是相同颜色的珍珠。
    白云希望能得到至少 (m) 个装满珍珠的瓶子,它想知道它的愿望能被实现的概率是多少呢?

    (n) 个在范围 ([1,D]) 内的整数均匀随机变量。
    求至少能选出 (m) 个瓶子,使得存在一种方案,选择一些变量,并把选出来的每一个变量放到一个瓶子中,满足每个瓶子都恰好装两个值相同的变量的概率。
    请输出概率乘上 (D^n) 后对 (998244353) 取模的值。

    数据范围

    测试点编号 (D) (n) (m)
    (25) (le 100000) (le 1000000000) (le n)

    所有测试点均满足 (0le mle 10^9,1le nle 10^9,1le Dle 10^5)

    解题思路

    显然如果 (m * 2 + D le n) 的话概率就是 1

    还是要推推式子

    (f_i) 表示至少有 i 个奇数的方案数,有

    [large f_i = n!{D choose i} left[x^n ight]left(frac {e^x-e^{-x}}{2} ight)^{i}e^{(D-i)x}\ large = n!{D choose i}frac 1{2^i} sum_{j=0}^ileft[x^n ight](-1)^{i-j}{ichoose j}e^{jx}e^{-(i-j)x}e^{(D-i)x}\ large = n!{D choose i}frac 1{2^i} sum_{j=0}^ileft[x^n ight](-1)^{i-j}{ichoose j}e^{(D-2(i-j))x}\ large = n!{D choose i}frac 1{2^i} sum_{j=0}^i(-1)^{i-j}{ichoose j}frac {(D-2(i-j))^n}{n!}\ large = n!D!frac 1{2^i(D-i)!} sum_{j=0}^ifrac{1}{j!(i-j)!}(-1)^{i-j}frac {(D-2(i-j))^n}{n!}\ large = frac {D!}{2^i(D-i)!} sum_{j=0}^ifrac{1}{j!}frac{(-1)^{i-j}(D-2(i-j))^n}{(i-j)!}\ ]

    最后二项式反演一下即可,要用多项式加速

    #include <queue>
    #include <vector>
    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #define MP make_pair
    #define ll long long
    #define fi first
    #define se second
    using namespace std;
    
    template <typename T>
    void read(T &x) {
        x = 0; bool f = 0;
        char c = getchar();
        for (;!isdigit(c);c=getchar()) if (c=='-') f=1;
        for (;isdigit(c);c=getchar()) x=x*10+(c^48);
        if (f) x=-x;
    }
    
    template<typename F>
    inline void write(F x, char ed = '
    ')
    {
    	static short st[30];short tp=0;
    	if(x<0) putchar('-'),x=-x;
    	do st[++tp]=x%10,x/=10; while(x);
    	while(tp) putchar('0'|st[tp--]);
    	putchar(ed);
    } 
    
    template <typename T>
    inline void Mx(T &x, T y) { x < y && (x = y); }
    
    template <typename T>
    inline void Mn(T &x, T y) { x > y && (x = y); }
    
    const int N = 300500;
    const int P = 998244353;
    ll A[N], B[N], E[N], inv[N], jie[N];
    
    void Print(ll *A, int len) {
    	for (int i = 0;i < len; i++)
    		write(A[i], ' ');
    	puts("");
    }
    
    ll fpw(ll x, ll mi) {
    	ll res = 1;
    	for (; mi; mi >>= 1, x = x * x % P)
    		if (mi & 1) res = res * x % P;
    	return res;
    }
    
    ll D, n, m;
    int r[N], lim = 1;
    void init(void) {
    	while (lim <= 2 * D) lim <<= 1;
    	int len = lim >> 1;
    	for (int i = 0;i < lim; i++)
    		r[i] = (r[i>>1]>>1) | ((i & 1) ? len : 0);
    	E[1] = 1;
    	for (int i = 2;i < lim; i <<= 1) {
    		ll *e0 = E + i / 2, *e1 = E + i;
    		ll w = fpw(3, (P - 1) / (i << 1));
    		for (int j = 0;j < i; j += 2) 
    			e1[j] = e0[j>>1], e1[j+1] = e1[j] * w % P;
    	}
    	jie[0] = jie[1] = inv[0] = inv[1] = 1;
    	for (int i = 2;i < lim; i++) {
    		jie[i] = jie[i-1] * i % P;
    		inv[i] = inv[P % i] * (P - P / i) % P;
    	}
    	for (int i = 2;i < lim; i++)
    		inv[i] = inv[i-1] * inv[i] % P;
    }
    
    void dft(ll *A) {
    	for (int i = 1;i < lim; i++)
    		if (r[i] > i) swap(A[i], A[r[i]]);
    	for (int i = 1;i < lim; i <<= 1) {
    		for (int j = 0;j < lim; j += (i << 1)) {
    			ll *f = A + j, *g = f + i; ll *e = E + i;
    			for (int k = 0;k < i; k++) {
    				int x = f[k], y = e[k] * g[k] % P;
    				f[k] = (x + y) % P, g[k] = (x + P - y) % P;
    			}
    		}
    	}
    }
    
    void idft(ll *A) {
    	dft(A); ll inv = fpw(lim, P - 2);
    	reverse(A + 1, A + lim);
    	for (int i = 0;i < lim; i++)
    		A[i] = A[i] * inv % P;
    }
    
    int main() {
    	read(D), read(n), read(m), init();
    	if (m * 2 > n) return puts("0"), 0;
    	if (m * 2 <= n - D) return write(fpw(D, n)), 0;
    	for (int i = 0;i <= D; i++) {
    		A[i] = inv[i], B[i] = fpw((D + P - 2 * i) % P, n) * inv[i] % P;
    		if (i & 1) B[i] = (P - B[i]) % P;
    	}
    	dft(A), dft(B);
    //	Print(A, lim), Print(B, lim);
    	for (int i = 0;i < lim; i++) A[i] = A[i] * B[i] % P;
    	idft(A);
    	for (int i = 0;i <= D; i++)	
    		A[i] = A[i] * jie[D] % P * fpw(2, P - 1 - i) % P * inv[D-i] % P * jie[i] % P;
    	for (int i = 0;i <= D; i++) B[D-i] = i & 1 ? P - inv[i] : inv[i];
    	for (int i = D + 1;i < lim; i++) A[i] = B[i] = 0;
    //	Print(A, D), Print(B, D);
    	dft(A), dft(B);
    	for (int i = 0;i < lim; i++) A[i] = A[i] * B[i] % P;
    	idft(A);
    	ll ans = 0;
    	for (int i = 0;i <= n - m - m; i++) ans = (ans + A[D + i] * inv[i]) % P;
    	write(ans);
    	return 0;
    }
    
  • 相关阅读:
    记录一个bug关于radio的
    at notFoundError …@cross-spawnlibenoent.js: 报错解决
    关于目前高清屏幕150%适配需要注意的样式写法
    记录一个css样式覆盖的问题。
    video.js使用详解(转载)
    记录一次node版本更新的问题,node的exe版本安装不上去。
    webstorm左侧导航栏背景变成黄色的,文件搜索,定位等一系列功能都不好用了?
    SCRIPT5007: 无法获取未定义或 null 引用的属性“xxx”
    VMWare中安装CentOS6.6不能上网的解决办法
    Unity出现 error building player exception android (invocation failed)
  • 原文地址:https://www.cnblogs.com/Hs-black/p/13445343.html
Copyright © 2020-2023  润新知