1. 程式人生 > 實用技巧 >Happy Necklace HDU - 6030(公式推導+矩陣快速冪)

Happy Necklace HDU - 6030(公式推導+矩陣快速冪)

題目連結:Happy Necklace HDU - 6030

華師男想為他的女朋友買一條項鍊。項鍊是由多個紅色和藍色珠子組成的單串。
身為華師男他體貼地想要更加打動他的女朋友,他知道,只要這段珠子中任意取出長度為質數的一段,都滿足紅珠數不少於藍珠數,她就會喜歡這條項鍊。
現在,他想買一串純正的有n個珠子的項鍊。他想知道滿足條件的可以使他的女朋友更加開心的不同項鍊的數量。
注意:項鍊是一長串的,無需考慮首尾相連的珠子。.

Input

輸入的第一行包含整數T(1<= T<=10000),表示測試用例數。
對於每個測試用例,存在一條包含整數n(2 <= n<=10^18)的一行,表示項鍊上的珠數。

Output

對於每個測試用例,輸出一行答案,答案可能很大,請輸出mod 10^9+7 之後的答案。

Sample Input

2
2
3

Sample Output

3
4

思路:給出一條項鍊,要求在這條項鍊中任取素數長度的一段中紅色珠子數量大於等於藍色珠子數量,求滿足條件的項鍊的數量。

1.對於素數長度的子串我們只需要考慮滿足最小的兩個素數2,3就可以了,大於3的長度都可以分解為由2,3組成的串。

2.模擬:
令 1 表示紅色珠子, 0 表示藍色珠子。設 n 為珠子數量。
當 n=2 時有:
1) 11
此時後面可以接 1或0 都可以滿足條件(任取長度為2或3的小段紅珠數量不小於藍珠數量).

2) 10
此時後面只能跟 1.

3) 01
此時後面只能跟 1.
由此可以得出當前兩位珠子顏色都為 1 時 後面才可以跟0。 即存在 1 1 0。
而在任何條件下後面都可以跟 1。 即 1 0 1、0 1 1、1 1 1 都滿足條件。

那麼對於任意長度大於為n(n>3)的項鍊 可以通過觀察長度為 n-1、n-2、n-3的項鍊 來推出第n位的珠子顏色有幾種方案。

1)首先在 n-1 長度項鍊的基礎上任何情況下接 1 都可以滿足條件,因此接 1 的情況數量就是 n-1 長度的總方案數量。
2)對於接 0 的情況需要滿足前兩位(即n-1n-2)都是 1 。而 n-11 的方案數量 是n-2長度的總方案數量,n-21 的方案數量是n-3
長度的總方案數量。
因此接 0 的情況數量就是 n-3 長度的總方案數量。
3)n長度的總方案數量 = 接1的情況數量 + 接0的情況數量 = n-1長度的方案數量+n-3長度的方案數量.


F(n) 表示長度為n的項鍊的方案數量


3.推得公式 F(n)=F(n-1)+F(n-3)
類似斐波那契數列
構造矩陣滿足
F(n)=F(n-1)+F(n-3)

F(n-1)=F(n-1)
F(n-2)=F(n-2)


AC程式碼:
 1 #include <set>
 2 #include <map>
 3 #include <list>
 4 #include <stack>
 5 #include <queue>
 6 #include <deque>
 7 #include <cmath>
 8 #include <string>
 9 #include <vector>
10 #include <cstdio>
11 #include <cstring>
12 #include <cstdlib>
13 #include <sstream>
14 #include <iostream>
15 #include <algorithm>
16 #include <unordered_map>
17 #define INF 0x3f3f3f3f
18 #define ll long long
19 #define ull unsigned long long
20 #define fcio ios::sync_with_stdio(false); cin.tie(0); cout.tie(0)
21 using namespace std;
22 const int maxn=3;
23 const int mod=1e9+7;
24 
25 struct Matrix
26 {
27     ll m[maxn][maxn];
28     Matrix() {memset(m,0,sizeof m);}
29 };
30 
31 Matrix Multi(Matrix a,Matrix b)
32 {
33     Matrix res;
34     for(int i=0;i<maxn;i++)
35     {
36         for(int j=0;j<maxn;j++)
37         {
38             for(int k=0;k<maxn;k++)
39             {
40                 res.m[i][j]=(res.m[i][j]%mod+a.m[i][k]%mod*b.m[k][j]%mod)%mod;
41             }
42         }
43     }
44     return res;
45 }
46 
47 Matrix fastm(Matrix a,ll n)
48 {
49     if(n==1) return a;
50     Matrix temp=fastm(a,n/2);
51     if(n%2) return Multi(Multi(temp,temp),a);
52     else return Multi(temp,temp);
53 }
54 
55 int main()
56 {
57     int t;
58     ll n;
59     fcio;
60     cin>>t;
61     while(t--)
62     {
63         cin>>n;
64         if(n<=3)
65         {
66             if(n==1) cout<<1<<endl;
67             else
68             cout<<n+1<<endl;
69         }
70         else
71         {
72             Matrix res;
73             res.m[0][0]=1;
74             res.m[0][1]=0;
75             res.m[0][2]=1;
76             res.m[1][0]=1;
77             res.m[1][1]=0;
78             res.m[1][2]=0;
79             res.m[2][0]=0;
80             res.m[2][1]=1;
81             res.m[2][2]=0;
82             res=fastm(res,n-3);
83             cout<<(4*res.m[0][0]%mod+3*res.m[0][1]%mod+2*res.m[0][2]%mod)%mod<<endl;
84         }
85     }
86 }