zoukankan      html  css  js  c++  java
  • 题解 LOJ #2527. 「HAOI2018」染色

    题目链接

    感觉网上的题解好像都是二项式反演,这里给出一种新的做法。

    我们先考虑按照 (W(i)=w_i) 做牛顿级数:

    [W(x)=sum_{t=0}^mc_tinom{x}{t} ]

    现在考虑这东西的组合意义:每个大小恰好为 (i) 的集合的贡献相当于是枚举它每个大小为 (t) 的子集,然后乘上一个贡献的系数。这样一来就可以直接枚举 (t),然后考虑有多少种情况可以找出一个大小为 (t) 的子集,这就是:

    [inom mtinom{n}{St}frac{(St)!}{(S!)^t}(n-St)^{m-t} ]

    总的答案就是:

    [sum_t c_tinom mtinom{n}{St}frac{(St)!}{(S!)^t}(n-St)^{m-t} ]

    直接做就没了。

    #include<poly.h>
    
    const int maxm = 1E+7 + 5;
    
    ll n = getll(), m = getll(), s = getll();
    ll Fac[maxm], Inv[maxm]; poly w, C;
    
    inline ll sgn(int x) { return x & 1 ? mod - 1 : 1; }
    inline ll binom(int n, int m) { return Fac[n] * Inv[m] % mod * Inv[n - m] % mod; }
    
    int main() {
    	Fac[0] = 1; int T = std::max(n, m);
    	for(int i = 1; i <= T; ++i)
    		Fac[i] = Fac[i - 1] * i % mod;
    	Inv[T] = fsp(Fac[T], mod - 2);
    	for(int i = T; i >= 1; --i)
    		Inv[i - 1] = Inv[i] * i % mod;
    	
    	for(int i = 0; i <= m; ++i) w[i] = getll() * Inv[i] % mod;
    	for(int i = 0; i <= m; ++i) C[i] = sgn(i) * Inv[i] % mod;
    	
    	C = C * w;
    	for(int i = 0; i <= m; ++i)
    		C[i] = C[i] * Fac[i] % mod;
    	
    	ll ans = 0;
    	for(int t = 0; t <= m && t * s <= n; ++t) {
    		(ans += C[t] * binom(n, t * s) % mod * binom(m, t) % mod *
    			fsp(m - t, n - s * t) % mod * Fac[t * s] % mod * fsp(Inv[s], t)) %= mod;
    	} putll(ans), IObuf::flush();
    }
    
  • 相关阅读:
    Spring boot核心注解
    Spring-boot配置文件
    JAVA操作Excel
    操作系统之基础
    Batch Normalization
    解决ios微信页面回退不刷新的问题
    textarea高度自适应,随着内容增加高度增加
    旋转卡 可以用做登录注册
    一个页面tab标签切换,都有scroll事件的解决办法
    input type="radio" 赋值问题
  • 原文地址:https://www.cnblogs.com/whx1003/p/14187253.html
Copyright © 2011-2022 走看看