これは、実際には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;
}
概要:行列の乗算を大幅にスペースを削減しました
この記事は、アイデアから取られている「の改善に関する記事。」