[2017百度之星程序设计大赛- 复赛] C

来源:互联网 发布:网络言论自由的特点 编辑:程序博客网 时间:2024/06/06 04:07

我们设 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 longconst 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;}


阅读全文
0 0
原创粉丝点击