格子染色(容斥原理)

第一次把公式自己推出来了当然看了百度百科后,真是激动呢~~~

题目描述

  棋盘是一个n×m的矩形,分成n行m列共n*m个小方格。现在萌萌和南南有C种不同颜色的颜料,他们希望把棋盘用这些颜料染色,并满足以下规定:

1.  棋盘的每一个小方格既可以染色(染成C种颜色中的一种) ,也可以不染色。 

2.  棋盘的每一行至少有一个小方格被染色。

3.  棋盘的每一列至少有一个小方格被染色。 

4.  每种颜色都在棋盘上出现至少一次。

以下是一些将3×3棋盘染成C = 3种颜色(红、黄、蓝)的例子:

请你求出满足要求的不同的染色方案总数。只要存在一个位置的颜色不同,即认为两个染色方案是不同的

 

输入

输入只有一行 3 个整数 n,m,c 。1 < = n,m,c < = 400

 

输出

输出一个整数,为不同染色方案总数。因为总数可能很大,只需输出总数mod 1,000,000,007的值。

 

具体分析:

首先像这样的题是可以用盒子与球的方法的。

我们把白色也当做一种颜色,则就有c+1个颜色,则总方案数(随便排)就是:(c+1)^{n*m}

根据容斥原理的加加减减就可以:

设i为随便i行,j为随便j列,k为随便k个不同的颜色,则就有:

\sum_{i=0}^{i<=n}\sum_{j=0}^{j<=m}\sum_{k=0}^{k<=c}C_{n}^{i}*C_{m}^{j}*C_{c}^{k}*(k+1)^{i*j}*(-1)^{n+m+c-i-j-k}

至于-1的指数,自己推一下就出来了。

现在时间复杂度是O(nmp),但是听某些同学说会超时,所以我们可以用二项式定理来优化一下(千万别用百度百科搜二项式,坑死你)

这样用乘法分配律变一下不要告诉我是错的

然后,我们发现后面的sigma很像二项式定理

(a+b)^n=C(n,0)a^n+C(n,1)a^(n-1)b+...+C(n,i)a^(n-i)b^i+...+C(n,n)b^n

我们先不看前面的,则就有:

∑C(m,j) *  (-(k+1)∧i)∧j

∧表示次方(该死的搜狗)

发现,把a带入上上个式子后,b不就为1嘛?

所以sigma就wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==​没有了

wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==

好懂吧(自作多情)

代码

由于G老师说我代码亮得太多,所以——————

我还是要亮!

就亮一下核心代码吧:

for( int i = 0 ; i <= n ; i ++ ){
        for( int k = 0 ; k <= p ; k ++ ){
            ll tmp = C( n , i ) * C( p , k ) % mod;
            tmp = tmp * qpow( 1 - qpow( k + 1 , i ) , m ) % mod;
            if( ( n + m + p - i - k ) % 2 )
                ans = ( ( ans - tmp ) + mod ) % mod;
            else
                ans = ( ( ans + tmp ) + mod ) % mod;
        }
    }

感觉亮了跟没亮区别不大eee

你可能感兴趣的:(数学,容斥原理,数论)