k-size字符串(组合数学)

k-size字符串(组合数学)

传送门

思路:因为要分成 k k 段,显然字符 a a 与字符 b b 的段数绝对值值差 1 \leq1

a a 分成 i i 段,即: i = k i , i + 1 = k i , i 1 = k i i=k-i,i+1=k-i,i-1=k-i

2 i 1 = k , 2 i = k , 2 i + 1 = k 2i-1=k,2i=k,2i+1=k .

显然当 k k 为偶数时,只有 2 i = k i = k 2 2i=k\rightarrow i=\dfrac{k}{2} 这种情况。

a b a\dots b b a b\dots a

k k 个位置放置相应的一个字符 a a b b

接下来就等价于将 n k 2 n-\dfrac{k}{2} 个数放入 k 2 \dfrac{k}{2} 个格子的方式.

也等价于 整数 n k 2 n-\dfrac{k}{2} 分成 k 2 \dfrac{k}{2} 个非负整数的方式。

f ( x , y ) f(x,y) 为整数x分成 y y 个非负整数的方式。

f ( x , y ) = f ( x , y 1 ) + f ( x 1 , y ) f(x,y)=f(x,y-1)+f(x-1,y) (这里 x 1 x-1 是保证第一个格子有数,不是第一个格子只放一个1)

即对应第一个数为0和第一个数不为0之和或者说是第一个格子不放东西和第一个格子放东西的方式之和。

根据观察这是一个组合数的递推:

根据 f ( n , 1 ) = 1 = C n + 1 1 n f(n,1)=1=C_{n+1-1}^n , f ( 1 , n ) = n = C 1 + n 1 1 f(1,n)=n=C_{1+n-1}^{1}

C x + y 1 x = C x + y 2 x + C x + y 2 x 1 C_{x+y-1}^{x}=C_{x+y-2}^{x}+C_{x+y-2}^{x-1}

所以可得 f ( x , y ) = C x + y 1 x f(x,y)=C_{x+y-1}^x

最后奇,偶数讨论一下即可得出答案。

需要注意的可能存在组合数的分母或分子 0 \leq0 的情况要舍去。

AC代码:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=1e5+5,mod=1e9+7;
#define mst(a) memset(a,0,sizeof a)
ll ksm(ll a,ll n){
        ll ans=1;
        while(n){
            if(n&1) ans=ans*a%mod;
            a=a*a%mod;
            n>>=1;
            }
    return ans;
}
ll inv(ll x){
        return ksm(x,mod-2);
   }
ll C(ll x,ll y){
    ll ans=1;
    for(int i=1;i<=y;i++) ans=ans*(x-i+1)%mod*inv(i)%mod;
    return ans;
}
ll f(ll x,ll y){
    if(y<=0||x<0) return 0;
    return C(x+y-1,x);
}
int main(){
	  int n,m,k;
      scanf("%d%d%d",&n,&m,&k);
      if(k&1){
        printf("%lld\n",(f(n-k/2-1,k/2+1)*f(m-k/2,k/2)%mod+f(n-k/2,k/2)*f(m-k/2-1,k/2+1)%mod)%mod);
      }
    else printf("%lld\n",2*f(n-k/2,k/2)*f(m-k/2,k/2)%mod);
	return 0;
} 

猜你喜欢

转载自blog.csdn.net/weixin_45750972/article/details/106187905