牡牛和牝牛(信息学奥赛一本通 1652)

【题目描述】

原题来自:USACO 2009 Feb. Silver

牡 mǔ,畜父也。牝 pìn,畜母也。 ——《说文解字》

约翰要带 N 只牛去参加集会里的展示活动,这些牛可以是牡牛,也可以是牝牛。牛们要站成一排,但是牡牛是好斗的,为了避免牡牛闹出乱子,约翰决定任意两只牡牛之间至少要有 K 只牝牛。

请计算一共有多少种排队的方法,所有牡牛可以看成是相同的,所有牝牛也一样,答案对 5000011 取模。

【输入】

一行,输入两个整数 N 和 K。

【输出】

一个整数,表示排队的方法数。

【输入样例】

4 2

【输出样例】

6

【提示】

样例说明

6 种方法分别是:牝牝牝牝,牡牝牝牝,牝牡牝牝,牝牝牡牝,牝牝牝牡,牡牝牝牡。

(母母母母,公母母母,母公母母,母母公母,母母母公,公母母公)

数据范围与提示:

对于全部数据,1N105,0K<N


 

由题意得要在两头公牛之间插入不少于规定数目的母牛,感觉上有点像隔板法,但是母牛的数量不一定,所以说似乎不太好做呢,我想了想也没想到该从何入手,所以就索性滚去看题接了,果然组合数学不是那么好想的呢,还不是因为我太菜了...

//参考题解:Cola

简单来说,就是枚举公牛的个数,然后算出此时最少需要多少头母牛(即(i-1)*k),那么此时就是在剩下的n-(i-1)*k个空位中放置这i头公牛,所以写成组合数的形式就是C(n-(i-1)*k,i)

但是注意要开long long哟,一开始我直接用int类型,最后一个点就RE了,后来我机智地把int改成定义long long(我真是太聪明了)就AC啦ㄟ(≧◇≦)ㄏ 

 1 #include
 2 #define int long long
 3 using namespace std;
 4 int N,p=5000011,k,ans;
 5 int mi(int a,int b)
 6 {
 7     int res=1;
 8     while(b)
 9     {
10         if(b&1)res=res*a%p;
11         a=a*a%p;
12         b>>=1;
13     }
14     return res;
15 }
16 int c(int n,int m)
17 {
18     if(nreturn 0;
19     int a=1,b=1;
20     for(int i=n-m+1;i<=n;i++)a=a*i%p;
21     for(int i=2;i<=m;i++)b=b*i%p;
22     return a*mi(b,p-2)%p;
23 }
24 int l(int n,int m)
25 {
26     if(!m)return 1;
27     else return c(n%p,m%p)*l(n/p,m/p)%p;
28 }
29 signed main()
30 {
31     cin>>N>>k;
32     for(int i=0;i<=N;i++)
33     {
34         int j=N-(i-1)*k;
35         if(jbreak;
36         ans=(ans+l(j,i))%p;
37     }
38     cout<<ans;
39     return 0;
40 }
View Code

 

 

转载于:https://www.cnblogs.com/ljy-endl/p/11414924.html

你可能感兴趣的:(牡牛和牝牛(信息学奥赛一本通 1652))