2021牛客暑期多校训练营2 B-Cannon(组合+推式子)

B-Cannon

首先 n n n个炮在一行操作一次的方案数为 2 ( n − 2 ) 2(n-2) 2(n2):前面两个炮只能向右吃,最后两个跑只能向左吃,而其余的炮既可以向左也可以向右,于是有 4 + 2 ( n − 4 ) 4+2(n-4) 4+2(n4)

于是操作 m m m次的操作排列的方案数 2 m ( n − 2 ) ( n − 3 ) . . . ( n − m − 1 ) = 2 m ( n − 2 ) ! ( n − 2 − m ) ! 2^m(n-2)(n-3)...(n-m-1)=2^m\frac {(n-2)!}{(n-2-m)!} 2m(n2)(n3)...(nm1)=2m(n2m)!(n2)!


n = a − 2 , m = b − 2 n=a-2,m=b-2 n=a2,m=b2

首先选择从 k k k选择 i i i次操作第一行,选择 k − i k-i ki次操作第二行,而问题一还需要从 k k k个位置选择出 i i i个按序放置操作序列,而问题二必须强制第一行操作放置在第二行操作前面,由此有:

对于问题1即是求
∑ 0 ≤ i ≤ k ( k i ) { 2 i n ! ( n − i ) ! } × { 2 k − i m ! [ m − ( k − i ) ] ! } = 2 k ∑ 0 ≤ i ≤ k k ! i ! ( k − i ) ! ⋅ n ! ( n − i ) ! ⋅ m ! [ m − ( k − i ) ] ! = 2 k k ! ∑ 0 ≤ i ≤ k ( n i ) ( m k − i ) = 2 k k ! ( n + m k ) \begin{aligned} &\sum_{0\leq i\leq k}\dbinom{k}{i}\{2^i\frac{n!}{(n-i)!}\}×\{2^{k-i}\frac{m!}{[m-(k-i)]!}\}\\ \\&=2^k\sum_{0\leq i\leq k}\frac{k!}{i!(k-i)!}·\frac{n!}{(n-i)!}·\frac{m!}{[m-(k-i)]!}\\ \\&=2^kk!\sum_{0\leq i\leq k} \dbinom{n}{i}\dbinom{m}{k-i}\\\\&=2^kk!\dbinom{n+m}{k} \end{aligned} 0ik(ik){2i(ni)!n!}×{2ki[m(ki)]!m!}=2k0iki!(ki)!k!(ni)!n![m(ki)]!m!=2kk!0ik(in)(kim)=2kk!(kn+m)


对于问题2即是求
∑ 0 ≤ i ≤ k { 2 i n ! ( n − i ) ! } × { 2 k − i m ! [ m − ( k − i ) ] ! } = 2 k ∑ 0 ≤ i ≤ k n ! ( n − i ) ! × m ! [ m − ( k − i ) ] ! = 2 k n ! m ! ( n + m − k ) ! ∑ 0 ≤ i ≤ k ( n + m − k ) ! ( n − i ) ! [ m − ( k − i ) ] ! = 2 k n ! m ! ( n + m − k ) ! ∑ 0 ≤ i ≤ k ( n + m − k n − i ) = 2 k n ! m ! ( n + m − k ) ! ∑ n − k ≤ i ≤ n ( n + m − k j ) \begin{aligned} &\sum_{0\leq i\leq k}\{2^i\frac{n!}{(n-i)!}\}×\{2^{k-i}\frac{m!}{[m-(k-i)]!}\}\\\\&=2^k\sum_{0\leq i\leq k}\frac{n!}{(n-i)!}×\frac{m!}{[m-(k-i)]!}\\\\&=2^k\frac{n!m!}{(n+m-k)!}\sum_{0\leq i\leq k}\frac{(n+m-k)!}{(n-i)![m-(k-i)]!}\\\\&=2^k\frac{n!m!}{(n+m-k)!}\sum_{0\leq i\leq k}\dbinom{n+m-k}{n-i}\\\\&=2^k\frac{n!m!}{(n+m-k)!}\sum_{n-k\leq i\leq n}\dbinom{n+m-k}{j} \end{aligned} 0ik{2i(ni)!n!}×{2ki[m(ki)]!m!}=2k0ik(ni)!n!×[m(ki)]!m!=2k(n+mk)!n!m!0ik(ni)![m(ki)]!(n+mk)!=2k(n+mk)!n!m!0ik(nin+mk)=2k(n+mk)!n!m!nkin(jn+mk)
其中下面一项是组合数种的连续多项之和,考虑前缀和!

∑ n − k ≤ j ≤ n ( n + m − k j ) = ∑ 0 ≤ j ≤ n ( n + m − k j ) − ∑ 0 ≤ j ≤ n − k − 1 ( n + m − k j ) = ∑ 0 ≤ j ≤ n ( n + m − k j ) − ∑ 0 ≤ j ≤ n − k − 1 ( n + m − k n + m − k − j ) = ∑ 0 ≤ j ≤ n ( n + m − k j ) − ∑ m + 1 ≤ j ≤ n + m − k ( n + m − k j ) = ∑ 0 ≤ j ≤ n ( n + m − k j ) − { ∑ 0 ≤ j ≤ n + m − k ( n + m − k j ) − ∑ 0 ≤ j ≤ m ( n + m − k j ) } = ∑ 0 ≤ j ≤ n ( n + m − k j ) + ∑ 0 ≤ j ≤ m ( n + m − k j ) − 2 n + m − k = sum ( n + m − k ) \begin{aligned} &\sum_{n-k\leq j\leq n}\dbinom{n+m-k}{j}\\\\&=\sum_{0\leq j\leq n}\dbinom{n+m-k}{j}-\sum_{0\leq j\leq n-k-1}\dbinom{n+m-k}{j}\\\\&=\sum_{0\leq j\leq n}\dbinom{n+m-k}{j}-\sum_{0\leq j\leq n-k-1}\dbinom{n+m-k}{n+m-k-j}\\\\&=\sum_{0\leq j\leq n}\dbinom{n+m-k}{j}-\sum_{m+1\leq j\leq n+m-k}\dbinom{n+m-k}{j}\\\\&=\sum_{0\leq j\leq n}\dbinom{n+m-k}{j}-\{\sum_{0\leq j\leq n+m-k}\dbinom{n+m-k}{j}-\sum_{0\leq j\leq m}\dbinom{n+m-k}{j}\}\\\\&=\sum_{0\leq j\leq n}\dbinom{n+m-k}{j}+\sum_{0\leq j\leq m}\dbinom{n+m-k}{j}-2^{n+m-k}=\text{sum}(n+m-k) \end{aligned} nkjn(jn+mk)=0jn(jn+mk)0jnk1(jn+mk)=0jn(jn+mk)0jnk1(n+mkjn+mk)=0jn(jn+mk)m+1jn+mk(jn+mk)=0jn(jn+mk){0jn+mk(jn+mk)0jm(jn+mk)}=0jn(jn+mk)+0jm(jn+mk)2n+mk=sum(n+mk)

考虑求出 S n , m = ∑ i = 0 m ( n i ) S_{n,m}=\sum_{i=0}^{m}\dbinom{n}{i} Sn,m=i=0m(in)关于 n n n的递推式

S n , m = ∑ i = 0 m ( n i ) = ∑ i = 0 m [ ( n − 1 i ) + ( n − 1 i − 1 ) ] = S n − 1 , m + S n − 1 , m − 1 \begin{aligned} S_{n,m}=\sum_{i=0}^{m}\dbinom{n}{i}&=\sum_{i=0}^{m}[\dbinom{n-1}{i}+\dbinom{n-1}{i-1}]\\&=S_{n-1,m}+S_{n-1,m-1} \end{aligned} Sn,m=i=0m(in)=i=0m[(in1)+(i1n1)]=Sn1,m+Sn1,m1

S n − 1 , m = ∑ i = 0 m ( n − 1 i ) = S n − 1 , m − 1 + ( n − 1 m ) \begin{aligned} S_{n-1,m}=\sum_{i=0}^{m}\dbinom{n-1}{i}&=S_{n-1,m-1}+\dbinom{n-1}{m} \end{aligned} Sn1,m=i=0m(in1)=Sn1,m1+(mn1)

带入可得出
S n , m = 2 S n − 1 , m − ( n − 1 m ) S_{n,m}=2S_{n-1,m}-\dbinom{n-1}{m} Sn,m=2Sn1,m(mn1)


由此可得出
sum ( x ) = ∑ 0 ≤ j ≤ n ( x j ) + ∑ 0 ≤ j ≤ m ( x j ) − 2 x = S x , n + S x , m − 2 x = 2 sum ( x − 1 ) − ( x − 1 n ) − ( x − 1 m ) \begin{aligned} \text{sum}(x)&=\sum_{0\leq j\leq n}\dbinom{x}{j}+\sum_{0\leq j\leq m}\dbinom{x}{j}-2^{x}\\\\&=S_{x,n}+S_{x,m}-2^x\\\\&=2\text{sum}(x-1)-\dbinom{x-1}{n}-\dbinom{x-1}{m} \end{aligned} sum(x)=0jn(jx)+0jm(jx)2x=Sx,n+Sx,m2x=2sum(x1)(nx1)(mx1)


Code
#include<bits/stdc++.h>
using namespace std;
using ll=long long;
template <class T=int> T rd()
{
    T res=0;T fg=1;
    char ch=getchar();
    while(!isdigit(ch)) {if(ch=='-') fg=-1;ch=getchar();}
    while( isdigit(ch)) res=(res<<1)+(res<<3)+(ch^48),ch=getchar();
    return res*fg;
}
const ll mod=1e9+9;
ll qmi(ll a,ll b)
{
    ll v=1;
    while(b)
    {
        if(b&1) v=v*a%mod;
        b>>=1;
        a=a*a%mod;
    }
    return v;
}
int n,m;
ll inv[10000010];
void solve1()
{
    ll ans=1;
    ll Two=1,Fact=1;
    ll C=1;
    for(int i=1;i<=n+m;i++)
    {
        Two=Two*2%mod;
        Fact=Fact*i%mod;
        C=C*(n+m-i+1)%mod*inv[i]%mod;
        ans^=((Two*Fact%mod*C%mod)+mod)%mod;
    }
    printf("%lld ",ans);
}
ll sum[10000010];

void solve2()
{
    ll Cn=1,Cm=1;
    sum[0]=1;
    
    for(int i=1;i<=min(n,m);i++) sum[i]=2*sum[i-1]%mod;
    for(int i=min(n,m)+1;i<=n+m;i++)
    {
        sum[i]=2*sum[i-1]-(i>n?Cn:0)-(i>m?Cm:0);
        if(i>n) Cn=Cn*i%mod*inv[i-n]%mod;
        if(i>m) Cm=Cm*i%mod*inv[i-m]%mod;
        sum[i]=(sum[i]%mod+mod)%mod;
    }
    ll Factn=1,Factm=1,Two=1;
    for(int i=1;i<=n;i++) Factn=Factn*i%mod;
    for(int i=1;i<=m;i++) Factm=Factm*i%mod;
    ll Inv=1;
    
    for(int i=1;i<=n+m;i++) Inv=Inv*inv[i]%mod;
    
    ll ans=Two*Factn%mod*Factm%mod*Inv%mod*sum[n+m]%mod;
    
    for(int i=1;i<=n+m;i++)
    {
        Two=Two*2%mod;
        Inv=Inv*(n+m-i+1)%mod;
        ans^=((Two*Factn%mod*Factm%mod*Inv%mod*sum[n+m-i]%mod)+mod)%mod;
    }
    printf("%lld\n",ans);
}
int main()
{
    n=rd()-2,m=rd()-2;
    inv[1]=1;
    for(int i=2;i<=n+m;i++) inv[i]=(mod-mod/i*inv[mod%i]%mod)%mod;
    solve1();
    solve2();
    return 0;
}

看着公式写代码都写了好长时间,wtcl

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值