bzoj3398 [Usaco2009 Feb]Bullcow 牡牛和牝牛(dp/组合数学)

题意:

约翰要带N(1≤N≤100000)只牛去参加集会里的展示活动,这些牛可以是牡牛,也可以是牝牛.
牛们要站成一排.但是牡牛是好斗的,
为了避免牡牛闹出乱子,约翰决定任意两只牡牛之间至少要有K(O≤K<N)只牝牛.
请计算一共有多少种排队的方法.所有牡牛可以看成是相同的,所有牝牛也一样.
答案对5000011取模。

数据范围:n<=1e5

解法:

解法1:
dp
令d(i,0/1)表示第i位放特殊牛/普通牛的方案数。
转移方程:
d(i,0)=d(i-k-1,0)+d(i-k-1,1)
d(i,1)=d(i-1,1)+d(i-1,0)

解法2:
组合数学
枚举选择的特殊牛的数量num,那么至少需要(num-1)*k只普通牛。
多出来的普通牛数量为t=n-num-(num-1)*k,这些插到num+1个普通牛堆里面,
这是球盒模型,n个相同的球放进m个不同的盒子里面,方案数为C(n+m-1,m-1),
带入一下数据,方案数为C(t+num,num)
需要转移的地方:因为t+num可能>1e5,因子阶乘预处理的范围要大一点

code(dp):
#include<bits/stdc++.h>
using namespace std;
#define int long long
const int maxm=1e5+5;
const int mod=5000011;
int d[maxm][2];
int n,k;
signed main(){
    ios::sync_with_stdio(0);
    cin>>n>>k;
    d[1][0]=d[1][1]=1;//0是特殊牛,1是普通牛
    for(int i=2;i<=n;i++){
        if(i-k-1>=1){
            d[i][0]=(d[i-k-1][0]+d[i-k-1][1])%mod;
            d[i][1]=(d[i-1][0]+d[i-1][1])%mod;
        }else{
            d[i][0]=1;
            d[i][1]=(d[i-1][0]+d[i-1][1])%mod;
        }
    }
    int ans=(d[n][0]+d[n][1])%mod;
    cout<<ans<<endl;
    return 0;
}
code(组合数学):
#include<bits/stdc++.h>
using namespace std;
#define int long long
const int maxm=2e5+5;
const int mod=5000011;
int fac[maxm];
int n,k;
int ppow(int a,int b,int mod){
    int ans=1%mod;a%=mod;
    while(b){
        if(b&1)ans=ans*a%mod;
        a=a*a%mod;
        b>>=1;
    }
    return ans;
}
int C(int n,int m){
    if(m<0||m>n)return 0;
    return fac[n]*ppow(fac[m]*fac[n-m]%mod,mod-2,mod)%mod;
}
signed main(){
    ios::sync_with_stdio(0);
    fac[0]=1;
    for(int i=1;i<maxm;i++)fac[i]=fac[i-1]*i%mod;
    cin>>n>>k;
    int ans=0;
    for(int i=0;i<=n;i++){
        int t=(i-1)*k;
        int remain=n-i-t;
        if(remain<0)break;
        ans+=C(remain+i,i);
        ans%=mod;
    }
    cout<<ans<<endl;
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值