总结:组合数
这$F$题好难啊...只会部分分做法,下面两个方法都是部分分做法。满分做法我去看看...会的话就补一下
部分分做法
方法1:
首先$A$能赢的条件很明显,假设在所有的牌里面取出$A$张$A$牌,$B$张$B$牌,$C$张$C$牌,那么$A$能赢当且仅当$A=n,B<m,C<k$
所以假设我们在拿出了$n$张$A$牌的情况下,中间穿插着拿了$B$张$B$牌,$C$张$C$牌,则有
$$\sum_{i=0}^{i<=m+k}C(n-1,i+n-1)*3^{m+k-i}*\sum_{j=0}^{j<=m,j<=k}C(i,j)$$
首先在$i+n-1$张牌中取$n-1$张$A$牌的方案为$C(n-1,n+i-1)$
注意:最后一张牌一定需要是$A$,所以就只能有$n-1$
而且剩下的牌数的排列为$3^{m+k-i}$,要乘上去
以及在$i+n-1$中$B$和$C$的排列为$C(i,j)$,也要乘起来
所以就得到了上面的公式
但是,上面的做法我打挂了...这个式子是对的,我算后面那个$\sum_{j=0}^{j<=m,j<=k}C(i,j)$那里我没有枚举好...查不出来啊...
我在理解了满分做法之后终于发现我挂在哪里了...
在枚举后面的东西的时候我没有分类讨论。但是改完后貌似还分少了一类...
$subtask_1$10个点我错了$2$个...然后$subtask_2$被我强行水过去$2$个点..
用$C$牌数量来分类:分为$j<k$,$j<m$,$j<i$(第三类我没分...不想去改了...)
对于第一种情况:$x=\sum_{j=0}^{j<k}C(i,j)$
对于第二种情况:$x=\sum_{j=0}^{j<m}C(i,k)$
对于第三种情况:请读者独立思考(知道有第三种情况是因为我去看了一下满分的做法...)
#include <bits/stdc++.h> using namespace std ; #define N 5010 #define ll long long const int mod = 1e9 + 7 ; int n , m , k ; ll fac[ N ] , ifac[ N ] ; ll power( ll a ,ll b ) { ll base = a , ans = 1 ; while( b ) { if( b&1 ) ans = ( ans * base ) % mod ; base = ( base * base ) % mod ; b >>= 1 ; } return ans ; } ll mul( ll x ,ll y ) { return ( 1ll * x * y ) % mod ; } ll inv( ll x ) { return power( x , mod - 2 ) % mod ; } int main() { scanf( "%d%d%d" , &n , &m , &k ) ; fac[ 0 ] = 1 ; for( int i = 1 ; i < N ; i ++ ) fac[ i ] = mul( fac[ i - 1 ] , i ) ; for( int i = 0 ; i < N ; i ++ ) ifac[ i ] = inv( fac[ i ] ) ; ll ans = 0 , sum = n + k + m ; for( int i = n ; i <= sum; i ++ ) {// 取出n张A牌 for( int j = 0 ; j <= m ;j ++ ) {//B牌数量 int C = i - n - j ;//C牌数量 if( C < 0 || C > k ) continue ; ll tmp = mul( fac[ i - 1 ] , mul( ifac[ n - 1 ] , mul( ifac[ j ] ,ifac[ C ] ) ) ) ; tmp = mul( tmp , power( 3 , sum - i ) ) ; ans = ( ans + tmp ) % mod ; } } printf( "%lld\n" , ans ) ; }