Codeforces Round #195 (Div. 2) D题Vasily the Bear and Beautiful Strings

时间:2023-03-09 15:40:11
Codeforces Round #195 (Div. 2) D题Vasily the Bear and Beautiful Strings

这场CF,脑子乱死啊。。。C题,搞了很长时间,结束了,才想到怎么做。B题,没看,D题,今天看了一下,很不错的组合题。

如果n和m都挺多的时候

以下情况都是变为1,根据偶数个0,最后将会为1,奇数个0,最后变为0,以1开头,全都是0.

0 1..

0 0 0 1....

0 0 0 0 0 1....

总的情况是C(n+m,m),算1也可以算出来。注意m = 1的时候特判,0的时候,我也全写的特判。

10^5的组合数,用费马小定理求逆元。看了下题解,题解直接来了个逆元。。

inv(a) = a^(mod-2),完全没看懂,查了查资料,明白了。。

a*inv(a) 模 mod = 1

因为mod是素数,根据费马小定理,a的p-1次方 对 p取余等于1, a^(mod-2)肯定是逆元。

算组合数,好高端啊。。。

 #include <cstdio>
#include <cstring>
#include <string>
#include <cmath>
#include <algorithm>
using namespace std;
#define MOD 1000000007
#define LL __int64
LL fact[];
LL fastmod(LL a,LL k)
{
LL b = ;
while(k)
{
if(k&)
b = a*b%MOD;
a = (a%MOD)*(a%MOD)%MOD;
k = k/;
}
return b;
}
LL comb(int n,int m)//如果取余是素数,根据费马小定理求逆元,快速求组合数
{
LL ans,a;
ans = fact[n];
a = fastmod((fact[n-m]*fact[m])%MOD,MOD-);
return (ans*a)%MOD;
}
int main()
{
int i,n,m,g;
LL ans,res;
scanf("%d%d%d",&n,&m,&g);
if(m == )
{
if(n% == )
{
printf("%d\n",g);
}
else
{
printf("%d\n",!g);
}
return ;
}
if(n == )
{
if(m == &&g == )
printf("1\n");
else if(m == &&g == )
printf("0\n");
else if(m > &&g == )
printf("1\n");
else
printf("0\n");
return ;
}
fact[] = ;
for(i = ;i <= n+m;i ++)
{
fact[i] = (fact[i-]*i)%MOD;
}
ans = comb(n+m,n);
res = ;
for(i = ;i <= n;i += )
{
if(m == ) break;
if(i + == n+m) break;
res = (res + comb(n+m-i-,m-))%MOD;
}
if(m == &&n% == )
res ++;
if(g == )
printf("%I64d\n",res);
else
{
ans = (ans - res + MOD)%MOD;
printf("%I64d\n",ans);
}
return ;
}