[AHOI2004]數字迷陣題解

題目描述

這裏寫圖片描述

傳送門:https://www.luogu.org/problem/show?pid=2544

輸入輸出格式

輸入格式:

每行有三個正整數,分別是i,j,m,其中i,j<=10^9,2<=m<=10^4。

輸出格式:

每行輸出對應的第i行,第j列的那個正整數對m取模的結果。

輸入輸出樣例

輸入樣例#1:

1 2 99

輸出樣例#1:

2

輸入樣例#2:

9 1 999

輸出樣例#2:

22

解決方案

首先我們可以判斷出每行都是變形的斐波那契數列,又因爲a[i][2]=2a[i][1](i1) ,所以本質上a[i][j] 只與第i行的第一個元素有關,那麼關鍵求a[i][1]

我們發現第一列增加的值爲2或3,其實我們可以發現第一次(第二行)+3,後面兩次(3,4行)分別+2-3,再後面的3次是前兩次的序列和,即3-2-3……

每一次往後推的項數滿足斐波那契數列,且就是前面兩次的那些項連起來.即第一列通項爲f[i]=i×t+t1 ,其中t=5+12

所以我們可以用O(1)的時間求

a[i][1]
,但是需要O(N)的時間求a[i][j] ,那麼我們可以令f[0]=1,f[1]=1,a=1,b=1 ,則

m=5+12 ,k=152 ,f[n]=kn×(1m)mn×(1k)km

f[n]=mn+1kn+15 ;

其實就是斐波那契數列通項公式

其他行就是初值不一樣而已,代碼不想寫註釋,自己都覺得奇醜無比……

代碼

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
using namespace std;

typedef long long LL;
int n,m,p;
int x[101][3][3],y[3][3],z[3][3],a[101],k1,k2,ans;
int i,j,k,l;

int main() {
    scanf("%d%d%d",&n,&m,&p);
    m--;
    x[0][1][2]=x[0][2][1]=x[0][2][2]=1;
    a[0]=1;
    for(i=1;a[i-1]*2<=m;i++) {
        a[i]=a[i-1]*2;
        for(j=1;j<=2;j++)
            for(k=1;k<=2;k++) 
                for(l=1;l<=2;l++)
                    x[i][j][k]=(x[i][j][k]+(LL)x[i-1][j][l]*x[i-1][l][k])%p;
    }
    y[1][1]=y[2][2]=1;
    for(i--;i>=0;i--) {
        if(a[i]<=m) {
            m-=a[i];
            for(j=1;j<=2;j++) 
                for(k=1;k<=2;k++)
                    for(l=1;l<=2;l++) 
                        z[j][k]=(z[j][k]+(LL)x[i][j][l]*y[l][k])%p;
            for(j=1;j<=2;j++) 
                for(k=1;k<=2;k++) {
                    y[j][k]=z[j][k];
                    z[j][k]=0;
                }
        }
    }
    k1=((LL)(n*(1+sqrt(5))/2+n-1))%p;
    k2=((2*k1-n+1)%p+p)%p;
    ans=((LL)k1*y[1][1]+(LL)k2*y[1][2])%p;
    printf("%d\n",ans);
    return 0;
}
發佈了39 篇原創文章 · 獲贊 7 · 訪問量 1萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章