传送门:https://agc021.contest.atcoder.jp/tasks/agc021_e
大致题意:
吃球的变色龙
• 笼子里有
N
N
N只变色龙。
• 变色龙在没吃东西的时候是蓝色的。它根据以下规则变色:
• 一只蓝色的变色龙在吃过的红球比蓝球多时变成红色。
• 一只红色的变色龙在吃过的蓝球比红球多时变成蓝色。
• 一开始,所有变色龙都没吃东西。你可以执行以下操作
K
K
K次来喂它们:
• 选择一个红球或蓝球。
• 扔进笼子。然后,其中一只变色龙吃掉球。
• 扔
K
K
K次球后,所有变色龙都是红色的。求你有多少种可能的扔
K
K
K个球的方案。 对
998244353
998244353
998244353取模。两种方案不同当且仅当存在
i
i
i使得第
i
i
i次操作扔的球颜色不 同。
•
1
<
=
N
,
K
<
=
5
∗
1
0
5
• 1<=N, K<=5*10^5
•1<=N,K<=5∗105
首先可以发现一个显然的结论:
一个变色龙最后为红色只有两种可能:
①吃的红球比蓝球多
②相同且最后一个为蓝球
显然
R
<
B
R<B
R<B时肯定不合法
我们讨论
R
=
B
R=B
R=B的时候
可以转化到图上,任意一种丢法对应着
(
0
,
0
)
(0,0)
(0,0)到
(
R
,
B
)
(R,B)
(R,B)的一条路线
显然最后一个球必须是蓝球
• 终点为蓝球
画到图上
• 路线不能与直线
y
−
x
>
=
B
−
N
−
1
y-x>=B-N-1
y−x>=B−N−1相交
这也很好理解。我们可以发现前面迫不得已多出来的变色龙后面的红球无法弥补
可以推导到 R > B R>B R>B的时候结论类似,不过不要求终点为蓝球
#include<bits/stdc++.h>
using namespace std;
#define rep(i,j,k) for(int i = j;i <= k;++i)
#define repp(i,j,k) for(int i = j;i >= k;--i)
#define rept(i,x) for(int i = linkk[x];i;i = e[i].n)
#define P pair<int,int>
#define Pil pair<int,ll>
#define Pli pair<ll,int>
#define Pll pair<ll,ll>
#define pb push_back
#define pc putchar
#define mp make_pair
#define file(k) memset(k,0,sizeof(k))
#define ll long long
#define ls ch[x][0]
#define rs ch[x][1]
int rd()
{
int sum = 0;char c = getchar();bool flag = true;
while(c < '0' || c > '9') {if(c == '-') flag = false;c = getchar();}
while(c >= '0' && c <= '9') sum = sum * 10 + c - 48,c = getchar();
if(flag) return sum;
else return -sum;
}
const int p = 998244353;
int n,k;
int fac[1001000];
int inv[1001000];
int max(int a,int b){return a>b?a:b;}
int del(int a,int b){return ((a-b)%p+p)%p;}
int calc(int a,int b){return (a+b)%p;}
int Pow(int a,int x)
{
int now = 1;
for(;x;x >>= 1,a = 1ll*a*a%p) if(x&1)now = 1ll*now*a%p;
return now;
}
int C(int i,int j)
{
if(j > i || j < 0) return 0;
int now = 1ll*fac[i]*inv[j]%p;
now = 1ll*now*inv[i-j]%p;
return now;
}
int main()
{
n = rd();k = rd();
int ans = 0;
fac[0] = 1;inv[0] = 1;rep(i,1,1000000) fac[i] = 1ll*fac[i-1]*i%p,inv[i] = Pow(fac[i],p-2);
rep(x,max((k+1)/2,n),k)
{//(x,n-x)
int y = (x*2==k?k-x-1:k-x),t = x-n+1;
ans = calc(ans,del(C(x+y,x),C(x+y,y-t)));
}
printf("%d\n",ans);
return 0;
}