我是靠谱客的博主 玩命白羊,最近开发中收集的这篇文章主要介绍HDU——2604 Queuing(矩阵快速幂或者技巧题),觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

     Queues and Priority Queues are data structures which are known to most computer scientists. The Queue occurs often in our daily life. There are many people lined up at the lunch time. 


     Now we define that ‘f’ is short for female and ‘m’ is short for male. If the queue’s length is L, then there are 2 L numbers of queues. For example, if L = 2, then they are ff, mm, fm, mf . If there exists a subqueue as fmf or fff, we call it O-queue else it is a E-queue. 
     Your task is to calculate the number of E-queues mod M with length L by writing a program. 

Input

Input a length L (0 <= L <= 10 6) and M.

Output

Output K mod M(1 <= M <= 30) where K is the number of E-queues with length L.

Sample Input

3 8
4 7
4 8

Sample Output

6
2
1

题意: 给你一个数L代表一个队的长度,男女不限,随便排,f代表女生,m代表男生,但是其中不能出现 fmf  、fff 这种子序列,问一共有多少种排的方法,结果需要mod m.

题解: 任意L ,因为不存在fmf,fff所以可以这样想:

          1. 最后一个为m 那么有 f(L-1) 个这种情况的。

           2.最后为mmf 那么有 f(L-3) 个这种情况的。

           3.最后为mmff 那么有 f(L-4) 个这种情况的

只有满足上面三种情况,才符合题意。  所以我们可以得出递推关系,f(L) = f(L-1) + f(L-3) + f(L-4). 但是我们需要找出前四个的种类数,也是比较好找了,他们是2,4,6,9 , L4可能比较难找,但是通过给的样例可以发现,设L4的时候有x种,那么根据样例可以得出x%7=2,x%8=1 所以 x=9。这样我们可以根据递推式写一种带有技巧的代码:

 

#include <iostream>
using namespace std;
int f[1000005];
int main(){
	f[1]=2;//前四个需要单独算出来
	f[2]=4;
	f[3]=6;
	f[4]=9;
	int l,m;
	while(cin >> l >> m){
		for (int i = 5; i <= l;i++){
		    f[i]=f[i-1]+f[i-3]+f[i-4];//递推式
		    if(f[i] > 10000){//这里控制,取模运算次数,也控制f[i]的大小,如果f[i]大于m就取模会超时,这也算是小技巧了
		    	f[i]%=m;
			}
	    }
	    cout << f[l]%m << endl;
	}
	return 0;
}

下面看一下正规做法,用到了矩阵快速幂。

矩阵快速幂关键是构造矩阵,怎么构造呢? 通过递推式构造,应该有递推式的题都应该想到矩阵快速幂(个人见解)。够造的时候需要连续(个人见解)就是说 f(L) = f(L-1) + f(L-3) + f(L-4).需要写成f(L) = f(L-1) + 0* f(L-2) + f(L-3) + f(L-4).然后开始构造。。

f(L-1)    1 0 1 1    f(L)

f(L-2)    1 0 0 0    f(L-1)

f(L-3)    0 1 0 0    f(L-2)

f(L-4)    0 0 1 0    f(L-3)

红色部分就是我们要的矩阵,剩下来的就好做了,需要的是“构造矩阵”的L-5+1次方的第一行乘以9,6,4,2然后相加就可以了,注意小与5需要单独考虑。上代码。

#include <iostream>
#include <cstring>
using namespace std;
struct hh{
	int a[20][20];
}x;
int p[5]={0,2,4,6,9};//用于单独考虑输出
int r[5]={9,6,4,2};//储存前四项后面有用
hh mul(hh x,hh y,int c){//矩阵快速幂
	hh w;
	memset(w.a,0,sizeof(w.a));//初始化别忘记
	for (int i = 0; i < 4;i++){
		for (int j= 0; j < 4;j++){
			for (int k = 0; k < 4; k++){
				w.a[i][j]=(w.a[i][j]%c+(x.a[i][k]%c*y.a[k][j]%c)%c)%c;
			}
		}
	}
	return w;
}
hh j_quick(hh a, int b,int c){//矩阵快速幂
	hh ans;
	memset(ans.a,0,sizeof(ans.a));//初始化别忘记
	for (int i = 0; i < 4;i++){
		ans.a[i][i]=1;
	}
	while(b!=0){
		if(b&1)  ans=mul(ans,a,c);
		b>>=1;
		a=mul(a,a,c);
	}
	return ans;
}
int main(){
	int l,m;
	while(cin >> l >> m){
		if(l<5){//单独考虑输出部分
			cout << p[l]%m << endl;
			continue;
		}
		memset(x.a,0,sizeof(x.a));
		for (int i = 0; i < 4;i++){//构造矩阵
			if(i!=1) x.a[0][i]=1;
			if(i<3)  x.a[i+1][i]=1;
		}
		hh z=j_quick(x,l-5+1,m);//计算“构造矩阵”的l-5+1次方
	    int sum=0;
	    for (int i = 0; i < 4;i++){//第一行乘以9,6,4,2,然后加和,    用到前面的r[5]
		    sum=(sum%m+(r[i]%m*z.a[0][i]%m)%m)%m;
	    }
	    cout << sum << endl;
	}
	return 0;
}

 

最后

以上就是玩命白羊为你收集整理的HDU——2604 Queuing(矩阵快速幂或者技巧题)的全部内容,希望文章能够帮你解决HDU——2604 Queuing(矩阵快速幂或者技巧题)所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(39)

评论列表共有 0 条评论

立即
投稿
返回
顶部