[2017百度之星程序設計大賽- 複賽] C - hdu6146

我們設 Bn 代表從某個角出發,然後走遍所有格子回到同一列的方案數目。

Bn=2×Bn−1=2n−1

同樣,我們設 An 代表從某個角出發,然後走遍所有格子的方案數。

則 An=Bn+2×An−1+4×An−2

其中 Bn 代表回到了當前列的方案數, An−1 代表先填滿當前列然後走到相鄰的列處理同樣的一個子問題, 

An−2 代表通過對角線方式先走完當前列與相鄰列的格子,然後剩下的 n−2 列即相同子問題。

因爲有四個角,所以我們的結果要乘以 4 ,即 4×An 。

當然,真實情況下我們不一定是從四個角出發的,還有另一種情況就是中間的列

考慮中間的第 i 列

我們可以先從第 i 列往左走完所有的格子回來,然後再往右走完所有的格子;

也可以先往右走完所有的格子回來,再往左走完所有的格子。

於是總的方案數即 2×(4×Bi−1×An−i+4×Bn−i×Ai−1) ,其中 2 代表第 i 列有兩個格子可選爲初始點, 4 代表分別向左右兩邊行走時的選擇方案數 2×2 。

#include<cstdio>
#define ll long long
const int N=10010,P=1000000007;
ll a[N],b[N],n;
int T;
int main()
{
	register int i,j;
    b[1]=1;
    for (i=2;i<=N;i++) b[i]=(b[i-1]*2)%P;
    a[1]=1;a[2]=6;
    for (i=3;i<=N;i++) a[i]=(2*a[i-1]+b[i]+4*a[i-2])%P;
    scanf("%d",&T);
    for (j=1;j<=T;j++)
	{
        int n;scanf("%d",&n);ll ans=0;
        for (i=2;i<=n-1;i++) ans=(ans+16*b[i-1]%P*a[n-i])%P;
        ans=(ans+4*a[n])%P;
        if (n==1) ans=2;
        printf("%lld\n",ans);
    }
    return 0;
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章