链接:https://ac.nowcoder.com/acm/contest/317/H
来源:牛客网
小a的学期
时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 524288K,其他语言1048576K
64bit IO Format: %lld题目描述
小a是一个健忘的人,由于他经常忘记做作业,因此老师对他很恼火。
小a马上就要开学了,他学期一共2n2n天,对于第ii天,他有可能写了作业,也可能没写作业,不过他自己心里还有点B数,因此他会写恰好nn天的作业
现在,小a需要安排他的学期计划,如果小a的学期中存在一天xx,在这之前的xx天中,他没写作业的天数 - 写作业的天数⩾k⩾k,那么老师就会把它开除,我们称这是一种不合法的方案
小a想知道他有多少种合法的方案输入描述:
第一行三个整数n,k,pn,k,p,pp表示对pp取模输出描述:
一个整数表示答案示例1
输入
2 1 100007输出
2说明
总共有2n=42n=4天 合法的方案有 写了 没写 写了 没写 写了 写了 没写 没写 注意:没写 写了 没写 写了 是一种不合法的方案,因为在第一天时没写的天数-写了的天数⩾1⩾1示例2
输入
10 5 10000007输出
169252备注:
1⩽n,k⩽106,p⩽109+71⩽n,k⩽106,p⩽109+7 不保证pp为质数!
//求(C(n*2,n)-C(n*2,n+k))%p;
模板题,但是模板选错了,一直WA!!!
使用素数去重,然后计算结果
This is the code
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<cstdlib>
#include<iostream>
#include<iomanip>
#include<list>
#include<map>
#include<queue>
#include<sstream>
#include<stack>
#include<string>
#include<set>
#include<vector>
using namespace std;
#define PI acos(-1.0)
#define EPS 1e-8
#define MOD 1e9+7
#define LL long long
#define ULL unsigned long long //1844674407370955161
#define INT_INF 0x7f7f7f7f //2139062143
#define LL_INF 0x7f7f7f7f7f7f7f7f //9187201950435737471
const int dr[]= {0, 0, -1, 1, -1, -1, 1, 1};
const int dc[]= {-1, 1, 0, 0, -1, 1, -1, 1};
// ios::sync_with_stdio(false);
// 那么cin, 就不能跟C的 scanf,sscanf, getchar, fgets之类的一起使用了。
const int MAXN = 2e6+6;
vector<LL > prim;
bool not_prime[MAXN|5];
//用筛法生成素数
void Prime()
{
for(LL i=2; i<MAXN; ++i)
{
if(!not_prime[i])
prim.push_back(i);
for(int j=0; j<prim.size()&&prim[j]*i<MAXN; ++j)
{
not_prime[prim[j]*i]=1;
if(!(i%prim[j]))//保证没有重复筛选
break;
}
}
}
//计算n!中素因子p的指数
LL Cal(LL x, LL p)
{
LL ret=0;
LL rec= p;
while(x>=rec)
{
ret+=x/rec;
rec*=p;
}
return ret;
}
//计算n的k次方对M取模,二分法
LL Pow(LL n, LL k, LL M)
{
LL ret = 1;
while(k)
{
if(k&1)
ret=(ret*n)%M;
n=(n*n)%M;
k>>=1;
}
return ret;
}
//计算C(n,m)%M
LL C(LL n,LL m,LL M)
{
LL ans=1;
LL num;
for(int i=0; i<prim.size() && prim[i]<=n; ++i)
{
num=Cal(n, prim[i])-Cal(m, prim[i])-Cal(n-m, prim[i]);
ans=(ans*Pow(prim[i], num, M))%M;
}
return ans%M;
}
int main()
{
Prime();
LL n,m,M;
scanf("%lld%lld%lld",&n,&m,&M);
printf("%lld\n",(C(2*n,n,M)-C(2*n,n+m,M)+M)%M);
return 0;
}