1. 程式人生 > 實用技巧 >Swift中的變數與常量

Swift中的變數與常量

HDU6314 Matrix

Problem Description

Samwell Tarly is learning to draw a magical matrix to protect himself from the White Walkers.
the magical matrix is a matrix with n rows and m columns, and every single block should be painted either black or white.
Sam wants to know how many ways to paint the matrix, satisfied that the final matrix has at least A rows, B columns was painted completely black. Cause the answer might be too big, you only need to output it modulo 998244353

.

Input

There might be multiple test cases, no more than \(5\). You need to read till the end of input.
For each test case, a line containing four integers \(n,m,A,B. 1≤n,m,A,B≤3000.\)

Output

For each test case, output a line containing the answer modulo 998244353.

思路:

容斥,先推式子

\[f(n,m)表示在大小為n*m的矩陣中每行、列均有白,\\容斥易得\\ f(n,m)=\sum_{i=0}^n\sum_{j=0}^m(-1)^{i+j}{n\choose i}{m\choose j}2^{(n-i)(m-j)} \\ F(n,m)表示矩陣大小為n*m的答案,\\顯然列舉多少行、列全黑,去除全黑後剩下的矩陣每行、列不能全黑\\ \\ F(n,m)=\sum_{i=A}^{n}\sum_{j=B}^{m}{n\choose i}{m\choose j}f(n-i,m-j) \\ F(n,m)=\sum_{i=A}^{n}\sum_{j=B}^{m}{n\choose i}{m\choose j}\sum_{k=0}^{n-i}\sum_{l=0}^{m-j}(-1)^{k+l}{n-i\choose k}{m-j\choose l} 2^{(n-i-k)(m-j-l)} \\ F(n,m)=\sum_{i=A}^{n}\sum_{j=B}^{m}\left[{n\choose i}\sum_{k=0}^{n-i}(-1)^k{n-i\choose k}\right]\left[{m\choose j}\sum_{l=0}^{m-j}(-1)^l{m-j\choose l}\right]2^{(n-i-k)(m-j-l)}\\ 列舉i、k得到第一部分的值,存下每個i+k對應的值g(i+k),\\同理可得每個j+l對應的值G(j+l),\\最後列舉i+k與j+l得到g(i+k)G(j+l)2^{(n-i-k)(m-j-l)}即為答案\\ 時間複雜度為O(n^2+m^2+nm) \]

\(\mathfrak{Talk\ is\ cheap,show\ you\ the\ code.}\)

#include<map>
#include<cmath>
#include<stack>
#include<deque>
#include<queue>
#include<cstdio>
#include<vector>
#include<climits>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
# define Type template<typename T>
# define ll long long
# define read read1<ll>()
Type T read1(){
    T t=0;char k;
    bool v=0;
    do (k=getchar())=='-'&&(v=1);while('0'>k||k>'9');
    while('0'<=k&&k<='9')t=(t<<3)+(t<<1)+(k^'0'),k=getchar();
    return v?-t:t;
}
ll qkpow(ll n,ll x,ll mo){
    if(!x)return 1;
    ll t=qkpow(n,x>>1,mo);
    t=t*t%mo;
    if(x&1)t=t*n%mo;
    return t;
}
# define mod 998244353ll
# define I 499122177ll
# define N 3000
ll fac[N|3],inv[N|3];
ll Ch(ll m,ll n){
    if(m<n)return 0;
    return fac[m]*inv[m-n]%mod*inv[n]%mod;
}
void init(){
    fac[0]=1;
    for(int i=1;i<=N;++i)
        fac[i]=fac[i-1]*i%mod;
    inv[N]=qkpow(fac[N],mod-2,mod);
    for(int i=N;i;--i)
        inv[i-1]=inv[i]*i%mod;
}
ll invi(ll x){return qkpow(x,mod-2,mod);}
ll f[6005],f1[6005];
int main(){
    init();
    int n,m,A,B;
    while(~scanf("%d %d %d %d",&n,&m,&A,&B)){
        ll ans=0;
        memset(f,0,sizeof(f));
        memset(f1,0,sizeof(f1));
        for(int i=A;i<=n;++i)
            for(int k=0;k<=n-i;++k)
                f[i+k]=(f[i+k]+1ll*(k&1?-1:1)*Ch(n-i,k)*Ch(n,i))%mod;
        for(int i=B;i<=m;++i)
            for(int k=0;k<=m-i;++k)
                f1[i+k]=(f1[i+k]+1ll*(k&1?-1:1)*Ch(m-i,k)*Ch(m,i))%mod;
        for(int i=A;i<=n;++i)
            for(int j=B,v=qkpow(2,(n-i)*(m-j),mod),x=invi(qkpow(2,n-i,mod));j<=m;v=1ll*x*v%mod,++j)
                ans=(ans+f[i]*f1[j]%mod*v)%mod;
        printf("%lld\n",(ans+mod)%mod);
    }
    return 0;
}