非010串
基准時間限制:1 秒 空間限制:131072 KB 分值: 80 如果一個01字符串滿足不存在010這樣的子串,那麼稱它為非010串。 求長度為n的非010串的個數。(對1e9+7取模) Input一個數n,表示長度。(n<1e15)Output
長度為n的非010串的個數。(對1e9+7取模)Input示例
3Output示例
7
解釋: 000 001 011 100 101 110 111
讀完題,這樣的題目肯定是能找到規律所在的,要不然數據太大根本無法算。假設現在給的長度是n,答案為f(n),那麼假設最後一位是0,前面有010的可能就有f(n-1)種,同樣假設最後一位是1,前面有010的可能就也有f(n-1),而這樣排除的話還存在著一個問題,就是最後為0的時候可能會出現前面是01而構成010,這樣就加重復了。所以假設前一位為1,再減去f(n-2),當然還可能前面是11而構成110而不是010,所以還要把多減的再加回來,即再加上一個f(n-3),這樣一來就可以推出一個公式,f(n)=2*f(n-1)-f(n-2)+f(n-3)。看到這個公式,數據有那麼大,所以我們用矩陣快速冪來進行處理就可以快速得出結果了。
下面是AC代碼:
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> using namespace std; const long long mod=1000000007; struct matrix { long long a[3][3]; }; matrix cal(matrix A,matrix B) { int i,j,k; matrix C; for(i=0;i<3;i++) { for(j=0;j<3;j++) { C.a[i][j]=0; for(k=0;k<3;k++) { C.a[i][j]=(C.a[i][j]+(A.a[i][k]*B.a[k][j])%mod+mod)%mod; } } } return C; } int out(matrix A,matrix B) { cout<<"s:"<<endl; cout<<A.a[0][0]<<" "<<A.a[0][1]<<" "<<A.a[0][2]<<endl; cout<<A.a[1][0]<<" "<<A.a[1][1]<<" "<<A.a[1][2]<<endl; cout<<A.a[2][0]<<" "<<A.a[2][1]<<" "<<A.a[2][2]<<endl; cout<<"base:"<<endl; cout<<B.a[0][0]<<" "<<B.a[0][1]<<" "<<B.a[0][2]<<endl; cout<<B.a[1][0]<<" "<<B.a[1][1]<<" "<<B.a[1][2]<<endl; cout<<B.a[2][0]<<" "<<B.a[2][1]<<" "<<B.a[2][2]<<endl; return 0; } matrix pow_mod(long long x) { matrix s,base; base.a[0][0]=2; base.a[1][0]=-1; base.a[2][0]=1; base.a[0][1]=1; base.a[1][1]=base.a[2][1]=0; base.a[1][2]=1; base.a[0][2]=base.a[2][2]=0; s.a[0][0]=7; s.a[0][1]=4; s.a[0][2]=2; s.a[1][0]=s.a[1][1]=s.a[1][2]=0; s.a[2][0]=s.a[2][1]=s.a[2][2]=0; out(s,base); while(x) { if(x&1) s=cal(s,base); base=cal(base,base); out(s,base); x>>=1; } return s; } int main() { long long n; long long ans; while(scanf("%lld",&n)!=EOF) { if(n==0) cout<<0<<endl; else if(n==1) cout<<2<<endl; else if(n==2) cout<<4<<endl; else if(n==3) cout<<7<<endl; else { matrix t=pow_mod(n-3); ans=t.a[0][0]%mod; cout<<ans<<endl; /*cout<<t.a[0][1]%mod<<endl; cout<<t.a[1][0]%mod<<endl; cout<<t.a[1][1]%mod<<endl;*/ } } return 0; }