一个小练习

【问题描述】
n根木棍在地面上摆成一排,从中选择k根木棍,使得任意两个被选的木棍之间至少隔了m根木棍,有多少种选法?
【输入描述】(A.in)
第一行包含3个整数n、k、m,分别为题目所描述的
【输出描述】(A.out)
输出答案,由于答案很大,需要mod1000000007.
【输入样例】1000 100 5
【输出样例】444301345
【数据范围】
对于30%的数据 : 1<=n<=10,1<=k<=10,0<=m<=10
对于100%的数据: 1<=n<=1000,1<=k<=1000,0<=m<=1000

【问题分析】
分析题意得,总木棍数至少需要(k-1)*m+k根;然而总有一些地方是不能放木棍的,这些木棍有(k-1)*m根,需要空出来,把它们减掉,剩下的就是一个排列组合的问题。

【注意事项】
1. 如果剩下的木棍少于k根,那么需要特判,方案数为0;
2. 求组合数的公式如下:

这里写图片描述
3. 由于答案很大,我们需要对其取模,那么就需要用到乘法逆元,这里既可以分别求出m! 与(n-m)!的乘法逆元再向乘,也可以先乘后求逆元;
4. 逆元是关于模数的,所以快速幂要算1000000007-2次方,别误认为是关于n!-2;
5. 输入输出!!

以下代码:

#include<iostream>
#include<cstdio>
#include<cstring>
#define mod 1000000007
int line,chose,ge;
long long jc[1010];
using namespace std;
long long jcheng(int x)
{
  long long ans=1;  
   for(int i=2;i<=x;i++)
     {
        if(jc[i]!=0) 
           ans=jc[i];
         else
          {
            ans=(ans%mod * i%mod)%mod;
            jc[i]=ans;
          }
     }
  return ans;   
}
long long ni(long long x)
{
    long long ans=1;
    long long m=mod-2;
    while(m>0)
      {
        if(m & 1) ans=(ans* (x%mod))%mod;
        x=(x*x)%mod;
        m>>=1;
      }
 return ans%mod;      
}
long long work(int m,long long n)
{
    long long t1,t2,t3,t4;
    t1=jcheng(n);
    t2=jcheng(m);
    t3=jcheng(n-m);
    t4=ni((t2*t3)%mod);
    return (t1%mod*t4%mod)%mod;
}
int main()
{
 freopen("A.in","r",stdin);
 freopen("A.out","w",stdout);   
  memset(jc,0,sizeof(jc));
  jc[0]=1;jc[1]=1;
  scanf("%d%d%d",&line,&chose,&ge);
  long long b=line- ge*(chose-1);
  if(b<chose||line<chose)//¿Û•Öµã£¡ 
   {    printf("0");  return 0;  }  
  printf("%lld",work(chose,b)%mod); 
return 0;   }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值