题意

有若干个人,喜欢唱跳rap篮球,数量给定。排成一行,如果有连续四个人分别喜欢唱跳rap篮球,那么不合法。求总方案数。


思路

容易想到枚举连续情况,然后删去,但是这样无法解决连续情况外的连续。

所以考虑容斥。

每次容斥的时候如果暴力求出方案会到\(O(n^3)\),所以可以用一个小trick优化一下:枚举哪些部分唱跳,哪些部分rap篮球,然后\(O(1)\)计算区内方案数。(此处是否选择唱跳并不重要,因为是对称的)

代码

#include <bits/stdc++.h>

using namespace std;

namespace StandardIO {

    template<typename T>inline void read (T &x) {
        x=0;T f=1;char c=getchar();
        for (; c<'0'||c>'9'; c=getchar()) if (c=='-') f=-1;
        for (; c>='0'&&c<='9'; c=getchar()) x=x*10+c-'0';
        x*=f;
    }

    template<typename T>inline void write (T x) {
        if (x<0) putchar('-'),x*=-1;
        if (x>=10) write(x/10);
        putchar(x%10+'0');
    }

}

using namespace StandardIO;

namespace Project {
    #define int long long

    const int N=1001;
    const int MOD=998244353;

    int n,a,b,c,d,ans;
    int C[N][N],sum[N][N];

    inline int query (int i,int l,int r) {
        if (r<l) return 0;
        if (l<=0) return sum[i][r];
        return (sum[i][r]-sum[i][l-1]+MOD)%MOD;
    }

    inline void MAIN () {
        read(n),read(a),read(b),read(c),read(d),a=min(n,a),b=min(n,b),c=min(n,c),d=min(n,d);
        for (register int i=0; i<=1000; ++i) {
            C[i][0]=sum[i][0]=1;
            for (register int j=1; j<=i; ++j) {
                C[i][j]=(C[i-1][j]+C[i-1][j-1])%MOD;
            }
            for (register int j=1; j<=1000; ++j) {
                sum[i][j]=(sum[i][j-1]+C[i][j])%MOD;
            }
        }
        for (register int i=0; i<=n/4; ++i) {
            int res=0,left=n-i*4;
            for (register int j=0; j<=left; ++j) {
                int rap=left-j;
                res=(res+C[left][j]*query(j,j-a,b)%MOD*query(rap,rap-c,d)%MOD)%MOD;
            }
            res=(res*C[i+left][i])%MOD;
            if (i&1) ans=(ans-res+MOD)%MOD;
            else ans=(ans+res)%MOD;
            --a,--b,--c,--d;
            if (a<0||b<0||c<0||d<0) break;
        }
        write(ans);
    }

    #undef int
}

int main () {
//  freopen(".in","r",stdin);
//  freopen(".out","w",stdout);
    Project::MAIN();
}
02-12 19:35