hdu4565(矩阵快速幂)

So Easy!

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 4459    Accepted Submission(s): 1467


Problem Description
  A sequence S n 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 S n.
  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 < 2 15, (a-1) 2< b < a 2, 0 < b, n < 2 31.The input will finish with the end of file.
 

Output
  For each the case, output an integer S n.
 

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

Sample Output
  
  
4 14 4
 
题意:计算 ,其中
其中⌈⌉为向上取整,如⌈3.14⌉=4,其中0< a, m < 2^15,(a-1)^2<b<a^2, 0<b,n< 2^31
解题思路:
要求解⌈(a+√b)^n⌉%m,已知(a+1)^2<b<a^2,所以a-1<√b<a,且0<a-√b<1,0<(a-√b)^n<1.
根据二项式开:(a+√b)^n=C(n,0)a^n+C(n,1)a^(n-1)*√b+C(n,2)a^(n-2)*b+...+C(n,n)b^n/2
(a-√b)^n=C(n,0)a^n-C(n,1)a^(n-1)*√b+C(n,2)a^(n-2)*b+...-C(n,n)b^n/2
所以令cn=(a+√b)^n+(a-√b)^n,cn为整数因为带根式的项都约去了,又因为⌈(a+√b)^n⌉为(a+√b)^n向上取整所以而cn即为一个整数所以cn=⌈(a+√b)^n⌉。
Sn=cn%m,接下来进行构造矩阵用矩阵快速幂即可
矩阵推导

Cn*[(a+√b)+(a-√b)]=[(a+√b)^n+(a-√b)^n]*[(a+√b)+(a-√b)]=

(a+√b)^(n+1)+(a-√b)^(n+1)+(a^2-b)*[(a+√b)^(n-1)+(a-√b)^(n-1)]=

Cn+1+(a^2-b)*Cn-1

即Cn+1=2aCn-(a^2-b)Cn-1

#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX 2
using namespace std;
typedef struct {
long long m[MAX][MAX];
}Matrix;
Matrix P={0,0,1,0};
Matrix I={1,0,0,1};
int mod;
Matrix Matrixmul(Matrix a,Matrix b)
{
    int i,j,k;
    Matrix c;
    for(i=0;i<MAX;i++)
        for(j=0;j<MAX;j++)
        {
            c.m[i][j]=0;
            for(k=0;k<MAX;k++)
            {
                c.m[i][j]+=(a.m[i][k]*b.m[k][j])%mod;
            }
            c.m[i][j]%=mod;
        }
        return c;
}
Matrix quickpow(long long n)
{
    Matrix m=P,b=I;
    while(n>0)
    {
        if(n%2==1)
            b=Matrixmul(b,m);
        n=n/2;
        m=Matrixmul(m,m);
    }
    return b;
}
int main()
{
    long long a,b,n;
    while(scanf("%lld%lld%lld%lld",&a,&b,&n,&mod)!=EOF)
    {

            P.m[0][0]=2*a;
            P.m[0][1]=b-a*a;
            P.m[1][0]=1;
            P.m[1][1]=0;
            P=quickpow(n);
            printf("%lld\n",((P.m[1][0]*2*a+P.m[1][1]*2)%mod+mod)%mod);
    }
    return 0;
}




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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值