Given a set S = {1, 2, ..., n}, number m and p, your job is to count how many set T satisfies the following condition:
- T is a subset of S
- |T| = m
- T does not contain continuous numbers, that is to say x and x+1 can not both in T
Input
There are multiple cases, each contains 3 integers n ( 1 <= n <= 109 ), m ( 0 <= m <= 104, m <= n ) and p ( p is prime, 1 <= p <= 109 ) in one line seperated by a single space, proceed to the end of file.
Output
Output the total number mod p.
Sample Input
5 1 11 5 2 11
Sample Output
5 6
这个题也是找规律。
规律其实很简单,就是一个组合数:C(n-m+1,m)
但是注意一下当n-m+1<m的时候输出0。
当然,组合数取余,自然要用到lucas定理咯~
代码:
#include<stdio.h>
#include<string.h>
#include<iostream>
using namespace std;
typedef long long ll;
ll power(ll p,ll n,ll m)
{
ll sq=1;
while(n)
{
if(n%2==1)
sq=(sq%m)*(p%m)%m;
p=(p%m)*(p%m)%m;
n=n/2;
}
return sq%m;
}
ll C(ll n,ll r,ll p)
{
ll i,res=1,t;
for(i=1;i<=r;i++)
{
res=(res%p)*((n-i+1)%p)%p;
t=power(i,p-2,p);
res=(res%p)*(t%p)%p;
}
return res;
}
ll lucas(ll n,ll r,ll p)
{
if(n<r)
return 0;
return C(n,r,p);
}
int main()
{
ll n,m,p,res,x,y;
while(cin>>n>>m>>p)
{
if(n==0&&m==0&&p==0)
break;
res=1;
x=n-m+1;
y=m;
if(x<y)
{
cout<<0<<endl;
continue;
}
while(x&&y)
{
res=res*lucas(x%p,y%p,p)%p;
if(res==0)
break;
x=x/p;
y=y/p;
}
cout<<res<<endl;
}
return 0;
}
本文探讨了如何利用组合数的性质和模运算解决特定问题,重点介绍了如何通过Lucas定理来计算组合数的模运算结果,适用于大规模数据处理场景。
1010

被折叠的 条评论
为什么被折叠?



