2017 Multi-University Training Contest - Team 2 - 1006

Function Fx,ysatisfies:
这里写图片描述

For given integers N and M,calculate Fm,1
modulo 1e9+7.
Input
There is one integer T in the first line.
The next T lines,each line includes two integers N and M .
1<=T<=10000,1<=N,M<2^63.
Output
For each given N and M,print the answer in a single line.
Sample Input

2
2 2
3 3

Sample Output

2
33

题目大意:给你一个N,M让你求满足上述三个式子的函数F(i,j).
求F(m,1)的值;

解题思路:一道数学题,数那么大肯定不能硬算,把式子化简得到能使用矩阵快速幂的公式。
化简过程如下:
这里写图片描述

这里写图片描述

这里写图片描述

这里写图片描述

AC代码:


#include <iostream>
#include <cstring>
#include<stdio.h>
using namespace std;
#define SIZE 2

struct matrix
{
    long long e[SIZE][SIZE];
    matrix()
    {
        memset(e, 0, sizeof(e));
    }
} A, A_n;

const long long mod = 1e9+7;      //上限

matrix operator*(matrix &a, matrix &b)///两个矩阵相乘,行上的每个元素对应乘以列上的每个元素然后求和
{
    matrix t;
    for (int i = 0; i < SIZE; ++i)
    {
        for (int j = 0; j < SIZE; ++j)
        {
            for (int k = 0; k < SIZE; ++k)
            {
                t.e[i][j] += a.e[i][k]*b.e[k][j];
                t.e[i][j] %= mod;
            }
        }
    }
    return t;
}

matrix quickpower(matrix &a, long long b)///求矩阵的a的b次方,原理同整数幂一样
{
    matrix ans;
    for (int i = 0; i < SIZE; ++i)
    {
        ans.e[i][i] = 1;
    }
    while (b)
    {
        if (b & 1) ans = ans * a;
        b >>= 1;
        a = a * a;
    }

    return ans;
}

int main(int argc, char const *argv[])
{
    int testn;
    scanf("%d", &testn);

    while (testn--)
    {
        long long n, m;
        scanf("%I64d %I64d", &n, &m);
        ///矩阵A
        A.e[0][0] = 0;
        A.e[1][0] = A.e[1][1] = 1;
        A.e[0][1] = 2;
        ///求得矩阵An
        A_n = quickpower(A, n);

        matrix b;
        if(n & 1)
        {
            ///矩阵B1
            b.e[0][0] = -1;
            b.e[0][1] = 2;
            b.e[1][0] = 1;
            b.e[1][1] = 0;
        }
        else
        {
            ///矩阵B0
            b.e[0][0] = b.e[1][1] = 1;
            b.e[0][1] = b.e[1][0] = 0;
        }
        ///矩阵An-B0(B1)
        A_n.e[0][0] -= b.e[0][0];
        A_n.e[0][1] -= b.e[0][1];
        A_n.e[1][0] -= b.e[1][0];
        A_n.e[1][1] -= b.e[1][1];

        A_n = quickpower(A_n, m-1);

        long long ans = (A_n.e[0][0] + A_n.e[1][0]) % mod;
        printf("%I64d\n", ans);
    }
    return 0;
}

还有直接推通项的直接得到:
F(m,1)=(2*k1^(m-1)+(1+(-1)^(n+1))/2)/3 其中k1=(2^n-1);
然后直接求。 (不是一般人能做的)
还有就是观察规律得到这个公式没啥说的。
AC代码:

#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
using namespace std;
const int MAX = 1e5 + 10;
const int mod = 1e9 + 7;
typedef long long LL;
LL km(LL a,LL b){
    LL ans = 1;
    while(b){
        if(b & 1) ans = (ans * a) % mod;
        b >>= 1; a = (a * a) % mod;
    }
    return ans;
}
int main()
{
    int T;
    scanf("%d",&T);
    while(T--){
        LL n,m;
        scanf("%lld %lld",&n,&m);
        LL k = (km(2,n) - 1 + mod) % mod;
        LL k1 = (km(k,m - 1) * 2) % mod;
        LL k2 = (1 + km(-1,n + 1)) * km(2,mod - 2);
        printf("%lld\n",((k1 + k2) % mod * km(3,mod - 2)) % mod);
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值