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

传送门

思路:因为要分成段,显然字符与字符的段数绝对值值差

分成段,即:

.

显然当为偶数时,只有这种情况。

个位置放置相应的一个字符

接下来就等价于将个数放入个格子的方式.

也等价于 整数分成个非负整数的方式。

为整数x分成个非负整数的方式。

(这里是保证第一个格子有数,不是第一个格子只放一个1)

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

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

根据,

所以可得

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

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

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;
}