HDU 5434 Peace small elephant



Problem Description
Xiao Ming likes playing the international chess ,especially like the elephant(it can move by slant while no barrier),

but he think the big elephant of the chess is cruel,and a kind of small elephant is not as cruel as the big elephant.

Its attack range is checks on the ramp of the small elephant's check's right angle.Now Ming is going to put many small elephants on his chessboard.

It's interesting that when two small elephants have a common side they'll become one solidarity elephant,

and more than 2 small elephants also can do this if satisfy the condition,and the attack range of solidarity elephants is same as the small elephant.

Now there is a requirement that it's empty on anyone of elephants' attack range(no piece).Xiao Ming has a special chessboard with  mn  checks.

Please figure out the number of all the plans that satisfy the condition.As the number is too big,we need to have a modulo  1000000007 .

The following is pictures show the attack range of elephants with different shape,"X"means attack range.


 

Input
There are at most  5  testcases .

For each testcase contains two integers  n,m  ,meaning as in the title.
1n1000000000,1m7
 

Output
For each testcase print a single integer - the number of all the plans that satisfy the condition.
 

Sample Input
  
  
1 1 2 3
 

Sample Output
  
  
2 50
递推出矩阵,然后快速幂
#include<map>
#include<cmath>
#include<queue>
#include<stack>
#include<string>
#include<cstdio>
#include<vector>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
typedef long long LL;
const int maxn = 1000000007;
LL T, n, m, a[128][128], b[128], ans;

bool check(int x, int y)
{
    for (int i = 0; i < n; i++) 
    {
        int k = 1 << i;
        if (x&k)
        {
            if (y&k) continue;
            if ((y >> 1)&k)
            {
                if (!((x >> 1)&k)) return false;
            }
            if ((y << 1)&k)
            {
                if (!((x << 1)&k)) return false;
            }
        }
    }
    return true;
}

void update()
{
    LL c[128][128] = { 0 };
    for (int i = 0; i < (1 << n); i++)
        for (int j = 0; j < (1 << n); j++)
            for (int k = 0; k < (1 << n); k++)
                (c[i][k] += a[i][j] * a[j][k]) %= maxn;
    for (int i = 0; i < (1 << n); i++)
        for (int j = 0; j < (1 << n); j++) a[i][j] = c[i][j];
}

void get()
{
    LL c[128] = { 0 };
    for (int j = 0; j < (1 << n); j++)
        for (int k = 0; k < (1 << n); k++)
            (c[k] += b[j] * a[j][k]) %= maxn;
    for (int i = 0; i < (1 << n); i++) b[i] = c[i];
}

int main()
{
    //scanf("%I64d", &T);
    //while (T--)
    while (scanf("%I64d%I64d", &m, &n) != EOF)
    {
        for (int i = 0; i < (1 << n); i++)
        for (int j = 0; j < (1 << n); j++) if (check(i, j)) a[i][j] = 1; else a[i][j] = 0;
        for (int i = 0; i < (1 << n); i++) b[i] = 1;
        for (int i = m - 1; i; i >>= 1)
        {
            if (i & 1) get();
            update();
        }
        ans = 0;
        for (int i = 0; i < (1 << n); i++) (ans += b[i]) %= maxn;
        printf("%I64d\n", ans);
    }
    return 0;
}


   
   
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值