列表

详情


NC53244. 帐篷

描述

译自 JOISC 2018 Day1 T3「テント / Tents

JOI君经营着一座露营地。露营地被划分为H行W列的矩阵,各行平行于东西方向,而各列平行于南北方向。从北向南数第i行和从东向西数第j列相交的格子表示为(i,j)。
JOI君想在格子里搭一些帐篷。每座帐篷必须占据刚好一个格子。没有两座帐篷会占据同一个格子。
每座帐篷在东、南、西、北四个方向之一有一个出入口。帐篷的出入口朝向必须满足以下条件:
  • 如果格子上都有帐篷,那么格子上的帐篷出入口必须朝南,而格子上的帐篷出入口必须朝北。
  • 如果格子上都有帐篷,那么格子上的帐篷出入口必须朝东,而格子上的帐篷出入口必须朝西。
JOI君想知道在露营地上搭起至少一顶帐篷的合法方案数。两种方案被认为是不同的,当且仅当有至少一个格子的状态(即是否存在帐篷或帐篷出入口的朝向)不同。
任务
给出露营地的相关信息,请求出在露营地上搭起至少一顶帐篷的合法方案数,对1000000007取模。

输入描述

仅一行两个以空格分开的整数H和W,表示JOI君经营的露营地有H行W列。

输出描述

输出一行,仅一个整数,表示在露营地上搭起至少一顶帐篷的合法方案数对1000000007取模的余数。

示例1

输入:

1 2

输出:

9

说明:

如下图所示,共有9种搭帐篷的方式。图中字母E,W,S,N分别代表出入口朝向东、西、南、北的帐篷。

示例2

输入:

4 3

输出:

3252

示例3

输入:

100 100

输出:

561068619

原站题解

上次编辑到这里,代码来自缓存 点击恢复默认模板

C++(clang++ 11.0.1) 解法, 执行用时: 154ms, 内存消耗: 35700K, 提交时间: 2022-10-31 22:26:32

#include<bits/stdc++.h>
#define ls u<<1
#define rs u<<1|1
#define fi first
#define se second
#define min amin
#define max amax
#define pb push_back
#define pq priority_queue
#define vt vector
#define lb(x) (x&-x)
#define sub(i,j) ((1LL*i-1LL*j)%k+k)%k
std::mt19937 rnd(233);
using namespace std;
using ll=long long;
using node=array<int,2>;
using nnode=array<int,3>;
//inline int read(){int x=0,f=1;char c=getchar();while(c<'0'||c>'9'){if(c=='-') f=-1;c=getchar();}while(c>='0'&&c<='9'){x=x*10+(c^'0');c=getchar();}return x*f;}
template<typename T=int>T read(){T x;cin>>x;return x;}
template<typename U,typename V>auto min(U x,V y){return x<y?x:y;}
template<typename U,typename V>auto max(U x,V y){return x>y?x:y;}
template<typename U,typename...V>auto min(U x,V...y){return min(x,min(y...));}
template<typename U,typename...V>auto max(U x,V...y){return max(x,max(y...));}
template<typename U,typename V>bool cmin(U &x,V y){return x>y?x=y,true:false;}
template<typename U,typename V>bool cmax(U &x,V y){return x<y?x=y,true:false;}
constexpr int mod=1e9+7;
//int qpow(int x,int n=mod-2){int y=1;for(;n;n>>=1,x=1LL*x*x%p)if(n&1)y=1LL*y*x%p;return y;}
inline ll qpow(ll a,ll n=mod-2){ ll ans = 1;while(n){if(n&1){ans*=a;}a*=a;n>>=1;}return ans;}
constexpr int N=3e3+10;
constexpr int inf=1e9;
constexpr double eps=1e-4;
const int Size=3005;
int n,m,dp[Size][Size];
void solve() {
	n=read();
	m=read();
	for(int i=0; i<=n; i++)	dp[i][0]=1;
	for(int i=0; i<=m; i++)	dp[0][i]=1;
	for(int i=1; i<=n; i++) {
		for(int j=1; j<=m; j++) {
			dp[i][j]=dp[i-1][j];
			dp[i][j]=(dp[i][j]+4ll*j%mod*dp[i-1][j-1]%mod)%mod;
			if(j>=2)dp[i][j]=(dp[i][j]+(ll)j*(j-1)/2%mod*dp[i-1][j-2]%mod)%mod;
			if(i>=2)dp[i][j]=(dp[i][j]+(ll)j*(i-1)%mod*dp[i-2][j-1]%mod)%mod;
		}
	}
	printf("%d",(dp[n][m]-1+mod)%mod);
}
signed main(){
	cin.sync_with_stdio(false);cin.tie(nullptr);cout.tie(nullptr);
	solve();
//	for(int T=read();T--;solve());
}

上一题