[CF1536E] Omkar and Forest
阿新 • • 發佈:2021-06-12
前言
結論題?結論題!
題目
題目大意:
\(t\) 組資料,給一個 \(n\) 行 \(m\) 列的網格,每個點要麼是 0
要麼是 #
。如果是 0
,那麼這個位置就是數字 \(0\),否則可以是任意非負整數。我們認為網格是好的,需要滿足以下兩個條件:
- 對於每兩個相鄰的格子,其中的數字之差的絕對值不超過 \(1\)。
- 如果一個格子裡面是正整數,那麼與它相鄰的格子中必須有一個數字嚴格小於它。
詢問有多少個合法的網格,對 \(10^9+7\) 取模。
\(1\le t\le 100;1\le n,m\le 2000;\sum n,\sum m\le 2000;nm\ge 2;\)
講解
其實當你讀完兩個條件的時候就應該醒悟過來:這不就是 BFS 的過程嗎?!
所以很顯然,如果我們確定了初始的 \(0\) 的位置,那麼整張圖就確定了!
所以答案就是 \(2^{cnt}\),其中 \(cnt\) 為 #
的個數。
就這樣?
然後發現過不了樣例,發現有種情況沒有考慮:
如果全是 #
,我們把全 \(1\) 的情況考慮進去了!
所以減一即可。
程式碼
//12252024832524 #include <cstdio> #include <cstring> #include <algorithm> #define TT template<typename T> using namespace std; typedef long long LL; const int MAXN = 2005; const int MOD = 1e9 + 7; int n,m; char a[MAXN][MAXN]; LL Read() { LL x = 0,f = 1;char c = getchar(); while(c > '9' || c < '0'){if(c == '-')f = -1;c = getchar();} while(c >= '0' && c <= '9'){x = (x*10) + (c^48);c = getchar();} return x * f; } TT void Put1(T x) { if(x > 9) Put1(x/10); putchar(x%10^48); } TT void Put(T x,char c = -1) { if(x < 0) putchar('-'),x = -x; Put1(x); if(c >= 0) putchar(c); } TT T Max(T x,T y){return x > y ? x : y;} TT T Min(T x,T y){return x < y ? x : y;} TT T Abs(T x){return x < 0 ? -x : x;} int qpow(int x,int y) { int ret = 1; while(y){if(y & 1) ret = 1ll * ret * x % MOD;x = 1ll * x * x % MOD;y >>= 1;} return ret; } int main() { // freopen(".in","r",stdin); // freopen(".out","w",stdout); for(int T = Read(); T ;-- T) { n = Read(); m = Read(); int ans = 0; for(int i = 1;i <= n;++ i) scanf("%s",a[i]+1); for(int i = 1;i <= n;++ i) for(int j = 1;j <= m;++ j) if(a[i][j] == '#') ans++; if(ans == 1) Put(2,'\n'); else if(ans == n*m) Put(qpow(2,ans)-1,'\n'); else Put(qpow(2,ans),'\n'); } return 0; }