【構造共軛函式+矩陣快速冪】HDU 4565 So Easy! (2013 長沙賽區邀請賽)

加貝木葦發表於2015-04-08

【題目連結】click here~~

【題目大意】:

 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! 

【解題思路】

給一張神圖,推理寫的灰常明白了,關鍵是構造共軛函式,這一點實在是要有數學知識的理論基礎,推出了遞推式,接下來就是矩陣的快速冪了。

給個大神的連結:構造類斐波那契數列的矩陣快速冪

神圖:click here~~

程式碼:

/*
* Problem: HDU No.4565
* Running time: 62MS
* Complier: G++
* Author: javaherongwei
* Create Time: 9:55 2015/9/21 星期一
*/

#include <bits/stdc++.h>
#include <stdio.h>
#include <string.h>
#include <iostream>
#include <algorithm>

using namespace std;
typedef long long LL;
const LL siz=2;          // max size of the matrix,
#define MODD(a,b) (((a%b)+b)%b)

LL A,B,N,M,ret;
struct mut
{
  LL mat[siz][siz];
  mut(){
      memset(mat,0,sizeof(mat));
  }
  void init(LL a,LL b,LL c,LL d){
      mat[0][0]=a;mat[0][1]=b;
      mat[1][0]=c;mat[1][1]=d;
  }
  mut operator *(const mut &c)
  {
      mut res;
      for(int i=0; i<siz; ++i){
          for(int k=0; k<siz; ++k){
              for(int j=0; j<siz; ++j){
                  res.mat[i][j]=MODD(res.mat[i][j]+mat[i][k]*c.mat[k][j],M);
              }
          }
      }
      return res;
  }
}AC;

mut poww(LL n)
{
    mut ans;
    ans.init(1,0,0,1);
    while(n){
        if(n&1) ans=ans*AC;
        n>>=1;
        AC=AC*AC;
    }
    return ans;
}

int main()
{
    while(~scanf("%lld %lld %lld %lld",&A,&B,&N,&M)){
        if(N<=1){
            printf("%lld\n",2*A%M);
        }
        else{
            AC.init(2*A,B-A*A,1,0);
            mut ans=poww(N-1);
            printf("%lld\n",MODD(2*A%M*ans.mat[0][0]+2*ans.mat[0][1],M));
        }
    } return 0;
}

相關文章