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; }