hdu4565So Easy!+矩阵快速幂+广义斐波拉契

原创 2016年08月31日 11:02:45

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, (a-1)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长沙赛区全国邀请赛——题目重现

直接递推构造矩阵,然后快速幂。参考上一篇博客:http://blog.csdn.net/xtulollipop/article/details/52382791
(a1)2<b<a2所以依然可以(a+b)n(ab)n相加。
向上取整就是向下取整+1,所以有答案2*An-1+1=2*An

#include<cstdio>
#include<cmath>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<cstdlib>
#include<queue>
#include<vector>
#include<map>
#include<stack>
#include<set>
using namespace std;
#define pi acos(-1.0)
#define EPS 1e-6    //log(x)
#define e exp(1.0); //2.718281828
//#define mod 1000000007
#define INF 0x7fffffff
#define inf 0x3f3f3f3f
#pragma comment(linker,"/STACK:102400000,102400000")
typedef long long LL;

#define debug(x) cout<<x<<endl;
#define debug2(x) cout<<x<<" ";

//#define MOD 10000007
LL MOD;
struct Mat{
    int n,m;
    LL mat[9][9];
};
Mat operator *(Mat a,Mat b){
    Mat c;
    memset(c.mat,0,sizeof(c.mat));
    c.n = a.n,c.m = b.m;

    for(int i=1;i<=a.n;i++){
        for(int j=1;j<=b.m;j++){
            for(int k=1;k<=a.m;k++){
                c.mat[i][j] += (a.mat[i][k]*b.mat[k][j])%MOD;
                c.mat[i][j] %= MOD;
            }
        }
    }
    return c;
}
Mat operator +(Mat a,Mat b){
    Mat c;
    memset(c.mat,0,sizeof(c.mat));
    c.n = a.n,c.m = a.m;

    for(int i=1;i<=a.n;i++){
        for(int j=1;j<=a.m;j++){
            c.mat[i][j] = (a.mat[i][j]+b.mat[i][j])%MOD;
        }
    }
    return c;
}
Mat operator ^(Mat a,LL k){
    Mat c;
    memset(c.mat,0,sizeof(c.mat));
    c.n = a.n,c.m = a.n;
    for(int i=1;i<=a.n;i++)c.mat[i][i] = 1;

    while(k){
        if(k&1){
            c = c*a;
        }
        a = a*a;
        k>>=1;
    }
    return c;
}
void out(Mat a){
    for(int i=1;i<=a.n;i++){
        for(int j=1;j<=a.m;j++){
            printf(j==a.m? "%I64d\n":"%I64d ",a.mat[i][j]);
        }
    }
}
LL quickPow(LL x, LL n, LL mm)
{
    LL a = 1;
    while (n)
    {
        a *= n&1 ? x : 1;
        a %= mm;
        n >>= 1 ;
        x *= x;
        x %= mm;
    }
    return a;
}
int main()
{
    LL a,b,n;
    while(scanf("%I64d %I64d %I64d %I64d",&a,&b,&n,&MOD)!=EOF){
        if(n==1){
            printf("%I64d\n",((LL)(a+ceil(sqrt(b*1.0)))%MOD));
            continue;
        }
        Mat pp;
        pp.n=pp.m=2;
        pp.mat[1][1]=a%MOD;
        pp.mat[1][2]=b%MOD;
        pp.mat[2][1]=1;
        pp.mat[2][2]=a%MOD;

        Mat A0;
        A0.n=2,A0.m=1;
        A0.mat[1][1]=a%MOD;
        A0.mat[2][1]=1;

        Mat ans=pp^(n-1);
        ans=ans*A0;
        printf("%I64d\n",(2*ans.mat[1][1])%MOD);
    }
    return 0;
}


/*
                   _ooOoo_
                  o8888888o
                  88" . "88
                  (| -_- |)
                  O\  =  /O
               ____/`---'\____
             .'  \\|     |//  `.
            /  \\|||  :  |||//  \
           /  _||||| -:- |||||-  \
           |   | \\\  -  /// |   |
           | \_|  ''\---/''  |   |
           \  .-\__  `-`  ___/-. /
         ___`. .'  /--.--\  `. . __
      ."" '<  `.___\_<|>_/___.'  >'"".
     | | :  `- \`.;`\ _ /`;.`/ - ` : | |
     \  \ `-.   \_ __\ /__ _/   .-` /  /
======`-.____`-.___\_____/___.-`____.-'======
                   `=---='
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
         I have a dream!A AC deram!!
 orz orz orz orz orz orz orz orz orz orz orz
 orz orz orz orz orz orz orz orz orz orz orz
 orz orz orz orz orz orz orz orz orz orz orz

*/

版权声明:本文为博主原创文章,未经博主允许不得转载。

相关文章推荐

循环节的长度,循环节,循环次数(kmp)

周赛题解     循环节的长度,循环节,循环次数(kms)       我想说这是一道签到题,意思就是本次测试中最水的一道,不过我这样说你真的愿意相信我吗?哈哈,题目是这样的给你一下小数,然后请告诉...

C++数组作为函数参数的几个问题

本文需要解决C++中关于数组的2个问题:1. 数组作为函数参数,传值还是传址?2. 函数参数中的数组元素个数能否确定?先看下面的代码。 #include using namespace std;voi...
  • tanghw
  • tanghw
  • 2011年06月19日 12:43
  • 9491

So Easy! ——————hdu4565(矩阵快速幂)

A sequence S n is defined as:  Where a, b, n, m are positive integers.┌x┐is the ceil of x. For exa...

hdu 4565 So Easy!(构造矩阵快速幂)

So Easy! Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total...

HDU 4565 So Easy!(矩阵快速幂)

So Easy! Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Total Sub...

HDU4565 So Easy!【矩阵快速幂】

题意:给出a,b,n,m。求 思路:(a + sqrt(b))^n = Xn + Yn * sqrt(b) (a+sqrt(b))^(n+1) = (Xn + Yn * sqrt(b)...
  • wjw1340
  • wjw1340
  • 2017年07月29日 18:59
  • 54

HDU4565-So easy-数学推导化简递推矩阵快速幂

So Easy! Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total S...

hdu - 4565 - So Easy!(矩阵快速幂)

题意:计算,其中( 0 题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4565 ——>>这里有个数学知识: (a+b√)n+(a−b√)n 是一个整数,...

Hdu 4565 So Easy! 矩阵快速幂+共轭数

So Easy! Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total...

hdu 4565 So Easy!(推公式&矩阵快速幂)

So Easy! Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total S...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:hdu4565So Easy!+矩阵快速幂+广义斐波拉契
举报原因:
原因补充:

(最多只允许输入30个字)