牛客挑战赛33 B-鸽天的放鸽序列

也许更好的阅读体验

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

如有哪里讲得不是很明白或是有错误,欢迎指正
如您喜欢的话不妨点个赞收藏一下吧

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值