zoukankan      html  css  js  c++  java
  • [BZOJ3398] [Usaco2009 Feb] Bullcow

    Description

    (n) 只牛,其中部分牛是特殊的,特殊的牛之间至少要隔 (k) 只普通牛。求方案数。(n le 10^5)

    Solution

    可以提供四种解法。

    DP + 前缀和

    (f[i]) 表示放了 (i) 只牛,最后一只是特殊牛的方案数,则

    [f[i]=sum_{j=0}^{i-k-1} f[j] ]

    前缀和优化即可。

    另一种 DP

    (f[i]) 表示放了 (i) 只牛的方案数,转移时考虑枚举上一只牛是普通还是特殊,则

    [f[i]=f[i-1]+f[i-k-1] ]

    注意前几位要特殊处理。

    更暴力的 DP

    (f[i][0/1]) 表示放了 (i) 只,最后一只是普通/特殊的方案数,则

    [f[i][0]=f[i-1][0]+f[i-1][1] \ f[i][1]=f[i-k-1][1]+f[i-k-1][0] ]

    显然这个方法化简一下就能直接得到第二种。

    组合数学

    枚举特殊牛的数量 (x),则至少需要 (k(x-1)) 只普通牛,多出来的普通牛数量为 (r=n-x-k(x-1)),而不同牛被分为 (x+1) 个段,因此我们要将 (r) 个球投入 (x+1) 个不同的盒子,球和球没有区别,盒子和盒子有区别,此时方案数为

    [inom {n+m-1}{m-1}=inom {x+r}{x} ]

    #include <bits/stdc++.h>
    using namespace std;
    
    #define int long long
    const int N = 100005;
    const int mod = 5000011;
    
    int f[N],n,k;
    
    signed main()
    {
        ios::sync_with_stdio(false);
        cin>>n>>k;
        for(int i=0;i<=k;i++) f[i]=i+1;
        for(int i=k+1;i<=n;i++) f[i]=(f[i-1]+f[i-k-1])%mod;
        cout<<f[n]<<endl;
    }
    
    
  • 相关阅读:
    Java线程的学习(一)——以售票系统为例
    web笔记
    ssm2之applicationContext.xml文件配置
    ssm笔记1
    在ViewHolder中添加item点击事件接口(自定义
    Java反射机制
    新手导航页(小圆点
    jsoup
    TextView设置随机大小和颜色
    常用IO流
  • 原文地址:https://www.cnblogs.com/mollnn/p/13669429.html
Copyright © 2011-2022 走看看