2020年牛客多校第五场C题

设一个二维数组 c c ,不能为0;

c [ 0 ] [ j ] = c [ 1 ] [ j ] c[0][j]=c[1][j]

再取一个数组 A A 和数组 B B ,可以为0

a [ i ] = A [ i ] + c [ 0 ] [ i ] a[i]=A[i]+c[0][i]

b [ i ] = B [ i ] + c [ 1 ] [ i ] b[i]=B[i]+c[1][i]

如给定 N = 4 , M = 4 , k = 2 N=4,M=4,k=2

你可以给 c c 数组赋值为 c [ 0 ] [ 1 ] = c [ 0 ] [ 2 ] = c [ 1 ] [ 1 ] = c [ 1 ] [ 2 ] = 1 c[0][1]=c[0][2]=c[1][1]=c[1][2]=1 ;

那么你的 A A 数组可以赋值为 A [ 1 ] = 2 , A [ 2 ] = 0 A[1]=2,A[2]=0

B B 数组可以赋值为 B [ 1 ] = 0 , B [ 3 ] = 2 B[1]=0,B[3]=2 ;

这样构造出一种 a b ab 数组便是 a = a= { 3 3 , 1 1 } b b ={ 1 1 , 3 3 }

如果确定了 c c 数组,且 i = 1 k c [ 0 ] [ i ] = r \sum\limits_{i=1}^{k}c[0][i]=r ,那么 A , B A,B 数组的组合数**(注意A,B数组中元素都可为0**)便是 C ( N r + k 1 , k 1 ) C ( M r + k 1 , k 1 ) C(N-r+k-1,k-1)*C(M-r+k-1,k-1) C ( n , m ) C(n,m) 表示 n n 个取 m m 个的组合数(因为 s u m ( c [ 0 ] ) + s u m ( A ) = N s u m ( c [ 1 ] ) + s u m ( B ) = M sum(c[0])+sum(A)=N且sum(c[1])+sum(B)=M 才是合法的)
对这样的c数组计数(即上面的组合数乘积)相当于对于所有任意 i = 1... k i=1...k 的都有 m i n ( a i , b i ) > = c [ 0 ] [ i ] min(a_i,b_i)>=c[0][i] 的ab数组都计了一次数

请往下看

考虑一个确定 a , b a,b 数列的 M I N MIN 数列,其中 M I N [ i ] = m i n ( a [ i ] , b [ i ] ) MIN[i]=min(a[i],b[i])

显然这个 a , b a,b 数列产生的贡献是 i = 1 = k M I N [ i ] \prod\limits_{i=1}^{=k}MIN[i] (这个是定义的)

**接下来来讨论一个确定的 M I N MIN 数组 M I N x MIN_x ,并且 a , b a,b 也是确定的 **

我们尝试把乘法拆成计数贡献。

那么显然对于特定的 M I N x MIN_x 数组,其应该要被计数的次数便是 i = 1 k M I N x [ i ] \prod\limits_{i=1}^{k}MIN_x[i] .

那么我们把这个计数分到每一个特定的 c c 数组和 A , B A,B 组合中去便可以了。

想一下,什么样的 c c 数组跟 A , B A,B 数组组成的 a , b a,b 数组会形成这个 M I N x MIN_x 数组(注意,a,b数组也是特定的了)呢。

显然是对于对于任意 i = 1.. k i=1..k 都有 c [ 0 ] [ i ] < = M I N X [ i ] c[0][i]<=MIN_X[i]

这样的 c c 数组跟 A , B A,B 的组合形成的 a , b a,b 数组的 M I N MIN 数组中一定会有跟 M I N x MIN_x 数组一样的。有且仅有一个

这样的 c c 数组会有多少个呢?

显然会有 i = 1 k M I N x [ i ] \prod\limits_{i=1}^{k}MIN_x[i] 个,因为你只要 c [ 0 ] c[0] 数组的每一位数都对应小于等于 M I N X MIN_X 就行了。

也就是说问题完美的转成计数问题了,即是转换成所有 c c 数组产生的 A , B A,B 数组的种数之和。

容易知道对于和相同的 c c 数组对应的 A , B A,B 数组个数是一样的,相同和如 r r 的种数有 C ( r 1 , k 1 ) C(r-1,k-1) 插板法

N = 3 , M = 3 , K = 2 N=3,M=3,K=2 为例

c [ 0 ] = c[0]= { 1 1 , 1 1 },则对应的 A , B A,B 数组组合有:

A 1 = A_1= { 0 0 , 1 1 }, B 1 B_1 ={ 0 , 1 0,1 },则 a 1 = 1 , 2 a_1=1,2 , b 1 = 1 , 2 b_1=1,2 , M I N 1 = 1 , 2 MIN_1=1,2

A 2 = 0 , 1 , B 2 = 1 , 0 A_2=0,1,B_2=1,0 ,则 a 2 = 1 , 2 a_2=1,2 , b 2 = 2 , 1 b_2=2,1 , M I N 2 = 1 , 1 MIN_2=1,1

接下来有 a 3 = 2 , 1 a_3=2,1 , b 3 = 1 , 2 b_3=1,2 , M I N 3 = 1 , 1 MIN_3=1,1

a 4 = 2 , 1 a_4=2,1 , b 4 = 2 , 1 b_4=2,1 , M I N = 2 , 1 MIN=2,1

这样对这个 c c 计数的话就相当于对以上四种 a , b a,b 都计了一次数了

手动模拟一下 c c 的其他数组对照上面的讲解就会迎刃而解了。

还是看不懂就是我不会解释

代码:

#include<bits/stdc++.h>
#define ll long long
#define endl '\n'
#define rep(i,l,r) for(int i=l;i<=r;i++)
#define per(i,r,l) for(int i=r;i>=l;i--)
const int MX=1e6+7;
const int mod=998244353;
const double pi=3.1415926535897932384;
double isp=1e-13;
using namespace std;
ll qpow(ll a,ll b,ll MOD=mod){for(ll ans=1;;a=a*a%MOD,b>>=1){if(b&1)ans=ans*a%MOD;if(!b)return ans;}}
ll inv(ll a,ll MOD=mod){return qpow(a,MOD-2,MOD);}//要求MOD为质数
ll exgcd(ll a,ll b,ll &x,ll &y){if(b==0){x=1,y=0;return a;}ll ret=exgcd(b,a%b,y,x);y-=a/b*x;return ret;}
ll getInv(int a,int mod){ll x,y;ll d=exgcd(a,mod,x,y);return d==1?(x%mod+mod)%mod:-1;}//求a在mod下的逆元,不存在逆元返回-1,不要求MOD为质数
ll p[MX],np[MX],in[MX];
ll C(ll n,ll m)
{
    return p[n]*np[m]%mod*np[n-m]%mod;
}
int main()
{
  ios::sync_with_stdio(0),cin.tie(0);
  p[0]=np[0]=in[1]=1;
  for(int i=1;i<MX;i++)p[i]=p[i-1]*i%mod;
  for(int i=2;i<MX;i++)in[i]=mod-(mod/i)*in[mod%i]%mod;
  for(int i=1;i<MX;i++)np[i]=np[i-1]*in[i]%mod;
  int t;
  cin>>t;
  while(t--)
  {
      int n,m,k;
      cin>>n>>m>>k;
      ll ans=0;
      for(int i=k;i<=min(n,m);i++)
      {
          ans=(ans+1ll*C(i-1,k-1)*C(n-i+k-1,k-1)%mod*C(m-i+k-1,k-1))%mod;

      }
      cout<<ans<<endl;
  }
  return 0;
}


猜你喜欢

转载自blog.csdn.net/weixin_43965698/article/details/107588107