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


    也许更好的阅读体验

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

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

  • 相关阅读:
    黑盒测试分类
    Java变量的初始化顺序
    javahttp请求四种方式
    mybatis sql查询慢
    jacoco搭配springMVC maven tomcat项目,单元测试&接口测试踩坑
    maven标签pluginManagement和plugins区别
    Java反射学习之Field类访问和修饰变量
    Classpath重新认识
    properties文件加载的六种方法
    VMware ESXI6.0安装和配置IP地址
  • 原文地址:https://www.cnblogs.com/Morning-Glory/p/11708523.html
Copyright © 2020-2023  润新知