2020年牛客多校第五场C题

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

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

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

a [ i ] = A [ i ] + c [ 0 ] [ i ] 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] b[i]=B[i]+c[1][i]

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

你可以给 c 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 c[0][1]=c[0][2]=c[1][1]=c[1][2]=1;

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

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

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

如果确定了 c c c数组,且 ∑ i = 1 k c [ 0 ] [ i ] = r \sum\limits_{i=1}^{k}c[0][i]=r i=1kc[0][i]=r,那么 A , B 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(Nr+k1,k1)C(Mr+k1,k1) C ( n , m ) C(n,m) C(n,m)表示 n n n个取 m 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 sum(c[0])+sum(A)=Nsum(c[1])+sum(B)=M才是合法的)
对这样的c数组计数(即上面的组合数乘积)相当于对于所有任意 i = 1... k i=1...k i=1...k的都有 m i n ( a i , b i ) > = c [ 0 ] [ i ] min(a_i,b_i)>=c[0][i] min(ai,bi)>=c[0][i]的ab数组都计了一次数

请往下看

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

A 2 = 0 , 1 , B 2 = 1 , 0 A_2=0,1,B_2=1,0 A2=0,1,B2=1,0,则 a 2 = 1 , 2 a_2=1,2 a2=1,2, b 2 = 2 , 1 b_2=2,1 b2=2,1, M I N 2 = 1 , 1 MIN_2=1,1 MIN2=1,1

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

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

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

手动模拟一下 c 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;
}


评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值