hdu 4565 So Easy!(矩阵乘法+共轭公式)

Problem Description
  A sequence Sn is defined as:

这里写图片描述
Where a, b, n, m are positive integers.┌x┐is the ceil of x. For example, ┌3.14┐=4. You are to calculate Sn.
  You, a top coder, say: So easy!

Input
  There are several test cases, each test case in one line contains four positive integers: a, b, n, m. Where 0<a,m<215,(a1)2<b<a2,0<b,n<231 .The input will finish with the end of file.

Output
  For each the case, output an integer Sn.

Sample Input
2 3 1 2013
2 3 2 2013
2 2 1 2013

Sample Output
4
14
4

Source
2013 ACM-ICPC长沙赛区全国邀请赛——题目重现

题目让求 (a+b)n 向上取整
因为出现了根号和向上取整,所以我们可以往凑整数方面想。
(a+b)n=xn+ynb
(ab)n=xnynb
(a1)2<b<a2,n>1 ,所以 (ab)n<1
所以 ceil(sn)=(a+b)n+(ab)n
所以 ceil(sn)=2xn

这样我们只需构造出矩阵求出 xn 就行了

sn=sn1(a+b)
xn+ynb=(axn1+byn1)+(xn1+ayn1)b

所以矩阵为:
(x10y10)(ab1a)

x1=a,y1=1

另一篇是hdu2256,是向下取整,可以一起看看。

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define LL long long
using namespace std;

LL mod;

struct Matrix
{
    long long m[2][2];
    int n;
    Matrix(int x)
    {
        n = x;
        for(int i=0;i<n;i++)
            for(int j=0;j<n;j++)
                m[i][j] = 0;
    }
    Matrix(int _n,LL a[2][2])
    {
        n = _n;
        for(int i=0;i<n;i++)
            for(int j=0;j<n;j++)
            {
                m[i][j] = a[i][j];
            }
    }
};
Matrix operator *(Matrix a,Matrix b)
{
    int n = a.n;
    Matrix ans = Matrix(n);
    for(int i=0;i<n;i++)
        for(int j=0;j<n;j++)
            for(int k=0;k<n;k++)
            {
                ans.m[i][j] += (a.m[i][k]%mod)*(b.m[k][j]%mod)%mod;
                ans.m[i][j] %= mod;
            }
    return ans;
}
Matrix operator ^(Matrix a,int k)
{
    int n = a.n;
    Matrix c(n);
    int i,j;
    for(i=0;i<n;i++)
        for(j=0;j<n;j++)
            c.m[i][j] = (i==j);
    for(;k;k>>=1)
    {
        if(k&1)
            c=c*a;
        a = a*a;
    }
    return c;
}

int main(void)
{
    LL a,b,n,m;
    while(scanf("%lld%lld%lld%lld",&a,&b,&n,&m)==4)
    {
        mod = m;
        LL aa[2][2] = { a,1LL,
                       0LL,0LL};
        Matrix A(2,aa);
        LL bb[2][2] = { a%mod,1LL,
                       b%mod,a%mod};
        Matrix B(2,bb);
        Matrix ans = A*(B^(n-1));
        printf("%d\n",ans.m[0][0]*2%mod);
    }

    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值