首页 > 代码库 > HDU 2604
HDU 2604
矩阵快速幂
设F(N)为字符串为N的时候,符合条件的子字符串数
以字符串最后一个字符为分界点,最后一个字符为m的时候,前N-1个字符没有限制,即为F(N-1);
当最后一个字符串为f的时候,就必须去除最后3个字符是fmf和fff的情况,此时最后3个字符可能为mmf和mff;
当后3个字符为mm时,前N-3个字符没有限制,即F(N-3);
但是当最后3个字符为mff时,后四个字符必须为mmff时前N-4个字符无限制,即为F(N-1);
所以递推为F(N)=F(N-1)+F(N-3)+F(N-4);
F0=0 F1=2 F2=4 F3=6 F4=9
1011 F(N-1) F(N)
1000 F(N-2) =F(N-1)
0100 F(N-3) F(N-2)
0010 F(N-4) F(N-3)
#include <iostream>
#include <string.h>
using namespace std;
int n,m;
struct M{
int t[4][4];
M(){
memset(t,0,sizeof(t));
}
void init(){
t[0][0]=t[0][2]=t[0][3]=t[1][0]=t[2][1]=t[3][2]=1;
}
void E(){
for(int i=0;i<4;i++){
t[i][i]=1;
}
}
};
M multiply(M a,M b){
M c;
for(int i=0;i<4;i++){
for(int j=0;j<4;j++){
for(int k=0;k<4;k++){
c.t[i][j]=(c.t[i][j]+a.t[i][k]*b.t[k][j])%m;
}
}
}
return c;
}
M powM(M a,int k){
M tem;
tem.E();
while(k){
if(k&1)tem=multiply(a,tem);
a=multiply(a,a);
k>>=1;
}
return tem;
}
int main(){
int t;
M a,b,c;
a.t[0][0]=9;
a.t[1][0]=6;
a.t[2][0]=4;
a.t[3][0]=2;
b.init();
while(cin>>n>>m){
if(n<5){
if(n==0)cout<<"0"<<endl;
else cout<<a.t[4-n][0]%m<<endl;
}
else {
c=powM(b,n-4);
c=multiply(c,a);
cout<<c.t[0][0]%m<<endl;
}
}
return 0;
}