D e s c r i p t i o n \mathcal{Description} Description
定义一个长为
n
n
n的
01
01
01序列
A
1
,
A
2
,
…
,
A
n
A_1, A_2, \dots, A_n
A1,A2,…,An的权值为
∑
i
=
1
n
(
(
∑
j
=
1
i
A
j
)
m
o
d
2
)
\sum_{i=1}^n ((\sum_{j=1}^i A_j) \bmod 2)
∑i=1n((∑j=1iAj)mod2),求有多少个长为
n
n
n的
01
01
01序列满足有恰好
k
k
k个
1
1
1,且权值最大。
答案对
1
0
9
+
7
10^9+7
109+7取模。
S o l u t i o n \mathcal{Solution} Solution
显然的两个贪心
- 最开始是 1 1 1最优
- 除最开始的 1 1 1外,之后出现 1 1 1两个两个出现最优
这样得到的一个序列的权值最大,其在大部分情况下是
1
1
1,只有
k
2
\frac{k}{2}
2k个是
0
0
0
如果有偶数个
1
1
1,那么就放一个
1
1
1在最后,这样
0
0
0只会出现这一次
方案数便考虑这些
0
0
0出现的位置
即在一堆
1
1
1后的空格内插入
k
2
\frac{k}{2}
2k个
0
0
0
用组合数直接算即可
C o d e \mathcal{Code} 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\n"),0;
--k,--n;
if (k&1) --k,--n;
printf("%d\n",C(n-k/2,k/2));
return 0;
}
如有哪里讲得不是很明白或是有错误,欢迎指正
如您喜欢的话不妨点个赞收藏一下吧