【学习笔记】[AGC040F] Two Pieces
我是丝薄因为我不会GF
考虑纯组合意义的推导。因为我真的不会数学啊
设 
     
      
       
       
         ( 
        
       
         x 
        
       
         , 
        
       
         d 
        
       
         ) 
        
       
      
        (x,d) 
       
      
    (x,d)表示最大值为 
     
      
       
       
         x 
        
       
      
        x 
       
      
    x,最小值和最大值之差为 
     
      
       
       
         d 
        
       
      
        d 
       
      
    d的方案数。那么相当于:
  
     
      
       
       
         1.1 
        
       
      
        1.1 
       
      
    1.1  
     
      
       
       
         d 
        
       
         ( 
        
       
         ≥ 
        
       
         2 
        
       
         ) 
        
       
      
        d(\ge 2) 
       
      
    d(≥2)减去 
     
      
       
       
         1 
        
       
      
        1 
       
      
    1
  
     
      
       
       
         1.2 
        
       
      
        1.2 
       
      
    1.2  
     
      
       
       
         x 
        
       
      
        x 
       
      
    x, 
     
      
       
       
         d 
        
       
      
        d 
       
      
    d同时加上 
     
      
       
       
         1 
        
       
      
        1 
       
      
    1
  
     
      
       
       
         1.3 
        
       
      
        1.3 
       
      
    1.3  
     
      
       
       
         d 
        
       
      
        d 
       
      
    d变成 
     
      
       
       
         0 
        
       
      
        0 
       
      
    0
显然操作 2 2 2的数目为定值。先固定每种操作的数目,那么合法的排列一定是 c 3 c_3 c3段折线,最后一段折线的终点高度恰好是 B − A B-A B−A,并且每一段折线除起点外都在 y = 1 y=1 y=1上方。
那么我们考虑,如果折线是连续的话,对于分段的位置,一定是后缀的最低点(换句话说是后缀和中严格最大的那个点),又因为后缀和是连续的所以恰好有 c 2 − c 1 c_2-c_1 c2−c1个这样的位置,并且最后一个分段的位置要恰好为 B − A B-A B−A,注意到开头也可以进行若干个操作 3 3 3,并且一段折线是空也是合法的,那么答案是 ( c 2 − c 1 − B + A + c 3 − 1 c 3 − 1 ) \binom{c_2-c_1-B+A+c3-1}{c_3-1} (c3−1c2−c1−B+A+c3−1)。又因为合法的折线数目是 ( c 1 + c 2 − 1 c 2 − 1 ) − ( c 1 + c 2 − 1 c 2 ) \binom{c_1+c_2-1}{c_2-1}-\binom{c_1+c_2-1}{c_2} (c2−1c1+c2−1)−(c2c1+c2−1),乘起来即可。
复杂度 O ( n ) O(n) O(n)。
#include<bits/stdc++.h>
#define fi first
#define se second
#define ll long long
#define pb push_back
#define inf 0x3f3f3f3f
using namespace std;
const int mod=998244353;
const int N=2e7+5;
int n,A,B;
ll fac[N],inv[N],res;
ll fpow(ll x,ll y=mod-2){
	ll z(1);
	for(;y;y>>=1){
		if(y&1)z=z*x%mod;
		x=x*x%mod;
	}return z;
}
void init(int n){
	fac[0]=1;for(int i=1;i<=n;i++)fac[i]=fac[i-1]*i%mod;
	inv[n]=fpow(fac[n],mod-2);for(int i=n;i>=1;i--)inv[i-1]=inv[i]*i%mod;
}
ll binom(int x,int y){
	if(x<0||y<0||x<y)return 0;
	return fac[x]*inv[y]%mod*inv[x-y]%mod;
}
ll solve(int c1,int c2,int c3){
	if(c3==0)return (c2-c1==B-A)?(binom(c1+c2-1,c2-1)-binom(c1+c2-1,c2)):0;
	return binom(c2-c1-B+A+c3-1,c3-1)*(binom(c1+c2-1,c2-1)-binom(c1+c2-1,c2))%mod;
}
signed main(){
	cin>>n>>A>>B,init(n<<1);
	if(A==0&&B==0){cout<<1;return 0;}
	for(int i=0;i<=n-B;i++){
		res=(res+solve(i,B,n-i-B))%mod;
	}cout<<(res+mod)%mod;
}

 
                
            
         浙公网安备 33010602011771号
浙公网安备 33010602011771号