(mathcal{Description})
定义一个长为(n)的(01)序列(A_1, A_2, dots, A_n)的权值为(sum_{i=1}^n ((sum_{j=1}^i A_j) mod 2)),求有多少个长为(n)的(01)序列满足有恰好(k)个(1),且权值最大。
答案对(10^9+7)取模。
(mathcal{Solution})
显然的两个贪心
- 最开始是(1)最优
- 除最开始的(1)外,之后出现(1)两个两个出现最优
这样得到的一个序列的权值最大,其在大部分情况下是(1),只有(frac{k}{2})个是(0)
如果有偶数个(1),那么就放一个(1)在最后,这样(0)只会出现这一次
方案数便考虑这些(0)出现的位置
即在一堆(1)后的空格内插入(frac{k}{2})个(0)
用组合数直接算即可
(mathcal{Code})
/*******************************
Author:Morning_Glory
LANG:C++
Created Time:2019年10月18日 星期五 19时01分41秒
*******************************/
#include <iostream>
#include <fstream>
using namespace std;
const int maxn = 1000006;
const int lim = 1000000;
const int mod = 1000000007;
int n,k,ans;
int fac[maxn],ifac[maxn],inv[maxn];
int C (int n,int m){ return 1ll*fac[n]*ifac[n-m]%mod*ifac[m]%mod;}
//{{{init
void init ()
{
fac[0]=ifac[0]=inv[1]=1;
for (int i=2;i<=lim;++i) inv[i]=(-1ll*mod/i*inv[mod%i]%mod+mod)%mod;
for (int i=1;i<=lim;++i) fac[i]=1ll*fac[i-1]*i%mod,ifac[i]=1ll*ifac[i-1]*inv[i]%mod;
}
//}}}
int main()
{
init();
cin>>n>>k;
if (!k) return printf("1
"),0;
--k,--n;
if (k&1) --k,--n;
printf("%d
",C(n-k/2,k/2));
return 0;
}
如有哪里讲得不是很明白或是有错误,欢迎指正
如您喜欢的话不妨点个赞收藏一下吧