09-02 HDU_Steps3.1 递推入门 HDU2041 HDU2044 HDU2045 HDU 2050 HDU2501 HDU2018 HDU1297 HDU2604

HDU Steps3.1 递推


3.1.1 HDU2041 超级楼梯  F(N)=F(N-1)+F(N-2)

3.1.2 HDU2044 一只小蜜蜂 F(N)=F(N-1)+F(N-2) N=终点-起点

3.1.3 HDU2018 母牛的故事 F(N)=F(N-1)+F(N-3)

3.1.4 HDU2050 折线分割平面 F(N)=2*N^2-N+1 递推,更简单的方法是用前三个点解三元一次方程组

3.1.5 HDU2501 Tiling_easy version F[N]=F(N-1]+2*F[N-2];

3.1.6 HDU2045 不容易系列之三-RGP难题 F[N]=F[N-1]+2*F[N-2]; F(1)=3,F[2]=6,F[3]=6
假如前N-1个是R------G 则第N个只能是B 一种选择

假如前N-2个是R------G则可以加RB或BG 两种选择


3.1.7 HDU1297 Children`s Queue F[N]=F[N-1]+F[N-2]+F[N-4];

F(n-1)+"M", F(n-2)+"FF", F(n-4)+"MFFF"

注意F(n-4)+"MF"不是要求序列,但再加上"FF"符合要求,所以要单独考虑.另外就是大数


3.1.8 HDU2604 Queuring

递推原理与上题类似F[N]=F[N-1]+F[N-3]+F[N-4];

但是直接O(N)的递推很慢,以前遇到过这题,用矩阵连乘可以加速到100MS左右(不优化4S+)

#include 
using namespace std;
int st[5][5]={
	{0,0,0,0,0},
	{0,0,1,0,0},
	{0,0,0,1,0},
	{0,0,0,0,1},
	{0,1,1,0,1},	
};
struct jz{
	int a[5][5];	
	//两种构造方法,一种清0,一种是相乘的矩阵 
	jz(int k){
		if(k==0)for(int i=1;i<=4;i++)for(int j=1;j<=4;j++)a[i][j]=0;
		if(k==1)for(int i=1;i<=4;i++)for(int j=1;j<=4;j++)a[i][j]=st[i][j];	
	}
	//矩阵相乘,乘法过程中模m 
	jz mult(jz jz2,int m){
		jz ans(0);
		for(int i=1;i<=4;i++)
		for(int j=1;j<=4;j++)
		for(int k=1;k<=4;k++)
			ans.a[i][j]=(ans.a[i][j]+a[i][k]*jz2.a[k][j])%m;	
		return ans;
	}
	//得到结果 
	int getr(){
		return a[4][1]*2+a[4][2]*4+a[4][3]*6+a[4][4]*9;
	}
};
jz dfs(int k,int m){
	if(k==1)return jz(1);
	//二分 
	jz rs=dfs(k/2,m);
	jz ans=rs.mult(rs,m);
	//处理为奇数的情况 
	if(k%2==1){
		jz t2=jz(1);
		jz tmp=ans.mult(t2,m);	
		ans=tmp;
	}
	return ans;
} 

int main(){
	int l,k;
	int a[5]={1,2,4,6,9};
	while(scanf("%d%d",&l,&k)!=EOF){
		if(l<=4)printf("%d\n",a[l]%k);
		else{
			jz ans=dfs(l-4,k);
			printf("%d\n",ans.getr()%k);	
		}	
	}	
}

你可能感兴趣的:(HDU_STEPS)