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