アイテムnおよびフィボナッチフィボナッチフロントNアイテムと

これは、実際には2つの質問ですが、彼らはすべての量は、対象の考えが似ているが、多くは鶏を揚げました。

フィボナッチ項目のn

タイトル説明
我々はすべて=それはシリーズ,. 1 = F1、F2をフィボナッチ知っている。1、F3 = 2、Fを=。3 ... +のFn = FN-FN-2。1、
F1 = 1、F2 = 1、2 = F3、F4 = 3、...、FN = FN -1 + FN-2。
今の問題は単純であり、入力N M、FNのmod Mを求めて

入力フォーマット
入力N、M。
出力フォーマット
のmodメートルFN出力

サンプル入力
51000
サンプル出力
5

フィボナッチ最初のn個のアイテムと

タイトル説明
我々はすべて=それはシリーズ,. 1 = F1、F2をフィボナッチ知っている。1、F3 = 2、Fを=。3 ... +のFn = FN-FN-2。1、
F1 = 1、F2 = 1、2 = F3、F4 = 3、...、FN = FN -1 + FN-2。
今の問題は簡単であり、入力N M、MOD M SN最初のn個のアイテムの{FN}を求めて

入力フォーマット
入力N、M。
出力フォーマット
のmodメートルFN出力

サンプル入力
51000
サンプル出力
12

数字の両方が非常に憂慮すべきであり、n <= 2 * 10 ^ $$されている {9} $$
配列は、単にいずれかを保存するため、テロ攻撃の木製の出現がありますが、私たちが伝統的なアイデアを使用しないことが明らかです、そうでなければ、私はこれを書いた時点では何です
そこでここでは、使用する必要があります行列の乗算
のチェイス、炉心にカットします。最初は、n番目のフィボナッチ項目は、我々が知ることができ、この質問です。

f[i]=1*f[i-1]+1*f[i-2]
f[i-1]=1*f[i-1]+0*f[i-2]

マトリックスとしてのそれらに変換される
$$
\ pmatrixの開始{}
F [I] \
F [-I 1]
\ pmatrixの終了{}
} {始めるpmatrixの= \を
。1. 1&\
。1&0
\}終了{pmatrixの*
\ {}開始pmatrixの
F [-I 1] \
F [I-2]
\}終了{pmatrixの
$$
ため

f[i]=1*f[i-1]+1*f[i-2]
f[i-1]=1*f[i-1]+0*f[i-2]

行列の乗算は(することができ私はあなたの行列の乗算を理解すると仮定します)ただ、マトリックスで得られた
し、我々が得ることができます:
$$
\ pmatrixの開始{}
F [I] \
F [。-I 1]
\ pmatrixのエンド{}
= \ {}始めるpmatrixの
。1. 1&\
。1&0
\ {} pmatrixのエンド
\のpmatrixの} {始める
。1. 1&\
。1&0
\ pmatrixの端部は、{}

\}開始{pmatrixの
F [I-2] \の
F [3-I]
\}終了{pmatrixのを
$$
これはされていジェーンは、一般式を導出することができる
$$
\のpmatrixの開始{}
F [I] \
F [-I 1]
\ pmatrixの終了{}
= \ pmatrixの開始{}
。1. 1&\
。1&0
\ ^ {}終了{pmatrixのを} 2-N-
\ pmatrixの開始{}
F [2] \
F [1]
\}終了{pmatrixの
$$
それ以来、行列乗算を連想することができるので、我々は、フラッシュ電源により、でき
$$
\ pmatrixの} {始める
。1. 1&\
。1&0
\}終了{pmatrixの
$$
数xとして、我々は使用でき$$ X ^ {N-2} $$それの値を求めるための高速動力。大幅そこに木でスペースを削減[0_0]

次にコード(私ははっきりと、コードを参照する必要が言いますか?

#include<cstdio>
#include<cstring>
#include<cmath>
using namespace std;
typedef signed long long ll;
struct node
{
    ll p[3][3];
    node(){memset(p,0,sizeof(p));}
};
int n;
ll M;
node A;
node plus(node a,node b)
{
    node c;
    for(int i=1;i<=2;i++)
        for(int j=1;j<=2;j++)
            for(int k=1;k<=2;k++)
                c.p[i][j]+=a.p[i][k]*b.p[k][j],c.p[i][j]%=M;
    return c;
}
node plus1(node a,node b,int n,int m,int p)
{
    node c;
    for(int i=1;i<=n;i++)
        for(int j=1;j<=p;j++)
            for(int k=1;k<=m;k++)
                c.p[i][j]+=a.p[i][k]*b.p[k][j],c.p[i][j]%=M;
    return c;
}
node mi(int n)//快速幂运算,也可以用while,因为这个有可能会爆栈
{
    if(n==1)return A;
    node t=mi(n/2);
    if(n%2==1)return plus(plus(t,t),A);
    else return plus(t,t);
}
int main()
{
    A.p[1][1]=1;A.p[1][2]=1;
    A.p[2][1]=1;A.p[2][2]=0;
    scanf("%d %llu",&n,&M);
    node c=mi(n-2),ha;//矩阵的幂运算
    ha.p[1][1]=1;ha.p[2][1]=1;//因为f[1]=f[2]=1,这是题目给出的
    c=plus1(c,ha,2,2,1);
    printf("%llu\n",c.p[1][1]%M);
    return 0;
}

次いで、この主題のようなアイデアを次の質問は、トピックので、それは[I] = {[I] F}と私は前に、それが描くことができる項目(S)

//这里我们用s[n-1],f[n],f[n-1]来表示这s[n],f[n+1],f[n]
s[n]=1*s[n-1]+1*f[n]+0*f[n-1]
//因为s[n]是前n个肥波数列的前缀和,所以他就是前n-1的前缀和加上第n个肥波数列
f[n+1]=0*s[n-1]+1*f[n]+1*f[n-1]
//那第n项的下一个就是f[n]+f[n-1]
f[n]=0*s[n-1]+1*f[n]+0*f[n-1]
//f[n]就为f[n]
//这样我们就建立起了关系

このアイデアはよく理解が、ちょっと考えにくいです!
次いで、マトリックスに彼の質問の画像のように、持っている
$$
} \ {pmatrixの開始
[N-] \ S
F [N- + 1] \
F [N-]
\ pmatrixの終了{} =
{}開始pmatrixの\
。1& 。1&0 \
0。1&1 \
0。1&0
\終了{pmatrixの} *
\開始{pmatrixの}
S [N - 1] \
F [N-] \
F [N - 1]
\エンド{pmatrixの}
$ $
あなたは常に一般式を簡素化することができ
$$
} \ pmatrixの{開始を
S [N-] \
F [N- + 1] \
F [N-]
\ pmatrixのエンド{} =
} {開始pmatrixの\
1。&0.1&\
0 &1. 1&\
0&0.1&
\}終了{pmatrixの1-N- ^ {}
\}は{始まるpmatrixの
Sの[を1] \
F [2] \
F [1]
\}終了{pmatrixの
$$
同じ考え、コード!

#include<cstdio>
#include<cstring>
#include<cmath>
using namespace std;
typedef signed long long ll;
struct node
{
    ll p[4][4];
    node(){memset(p,0,sizeof(p));}
};
int n;
ll M;
node A;
node plus(node a,node b)
{
    node c;
    for(int i=1;i<=3;i++)
        for(int j=1;j<=3;j++)
            for(int k=1;k<=3;k++)
                c.p[i][j]+=a.p[i][k]*b.p[k][j],c.p[i][j]%=M;
    return c;
}
node plus1(node a,node b,int n,int m,int p)
{
    node c;
    for(int i=1;i<=n;i++)
        for(int j=1;j<=p;j++)
            for(int k=1;k<=m;k++)
                c.p[i][j]+=a.p[i][k]*b.p[k][j],c.p[i][j]%=M;
    return c;
}
node mi(int n)
{
    if(n==1)return A;
    node t=mi(n/2);
    if(n%2==1)return plus(plus(t,t),A);
    else return plus(t,t);
}
int main()
{
    A.p[1][1]=1;A.p[1][2]=1;A.p[1][3]=0;
    A.p[2][1]=0;A.p[2][2]=1;A.p[2][3]=1;
    A.p[3][1]=0;A.p[3][2]=1;A.p[3][3]=0;
    scanf("%d %llu",&n,&M);
    node c=mi(n-1),ha;
    ha.p[1][1]=1;ha.p[2][1]=1;ha.p[3][1]=1;
    c=plus1(c,ha,3,3,1);
    printf("%llu\n",c.p[1][1]%M);
    return 0;
}

概要:行列の乗算を大幅にスペースを削減しました

この記事は、アイデアから取られている「の改善に関する記事。」

おすすめ

転載: www.cnblogs.com/candy067/p/11401960.html