您的位置:首页 > 其它

hdu 2604矩阵快速排序

2016-11-09 20:38 232 查看
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 2L 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

 

Author

WhereIsHeroFrom

 

Source

HDU 1st “Vegetable-Birds
Cup” Programming Open Contest

 

快速幂算法

long long pow_mod( long long a,long long i,long long n)

{

if(i==0) return 1%n;

int temp=pow_mod(a,i>>1,n);

temp =temp*temp%n;

if(i&1)

temp=(long long)temp*a%n;

return temp;

}

题意

  f和m两种字母组成字符串,fmf 和 fff 这种为不安全的字符串,现在有2*L个字母,问你有多少安全的字符串。答案mod M。

分析

  递推,这题本意是要用矩阵快速幂。不过我发现这题好神奇,只要适当的减少取模的次数,就可以水过去(呵呵呵)。

  当时做这题的时候用的是比较奇怪的递推式,然后超时了,但是两个两个地推也就水过去了(哈哈哈)。

  正确的递推方程:f(n)=f(n-1)+f(n-3)+f(n-4)。

  如果第n位是f,它前面是f时(ff),再前一位必须是m(mff),再前一位还必须是m(mmff),所以有f(n-4)种;

         它前面是m时(mf),再前一位必须是m(mmf),再前就任意了,所以有f(n-3)种

  第n位是m,它前面可以是任意的,所以有f(n-1)种。

  接下来是构造矩阵:



代码

矩阵快速幂代码(AC)

#include<stdio.h>
#include<string.h>
int k,m,t[5]={0,2,4,6,9};
struct matrix
{
int a[15][15];
int row,col;
void init(int row,int col){
this->row=row;
this->col=col;
memset(a,0,sizeof(a));
}
}u;
struct matrix b{
{{1,0,1,1},
{1,0,0,0},
{0,1,0,0},
{0,0,1,0}},
4,4
};
struct matrix c{
{{9},{6},{4},{2}},
4,1
};
matrix mul(matrix a,matrix b)
{
matrix c;
c.init(a.row,b.col);
for(int i=0; i<a.row; i++)
for(int j=0; j<b.col; j++)
for(int k=0; k<a.col; k++)
c.a[i][j]=(c.a[i][j]%m+a.a[i][k]*b.a[k][j]%m)%m;
return c;
}

matrix qpow(matrix a,int k)
{
matrix ans;
ans.init(a.row,a.col);
for(int i=0;i<a.row;i++)
ans.a[i][i]=1;
while(k)
{
if(k&1)ans=mul(ans,a);
a=mul(a,a);
k>>=1;
}
return ans;
}

int main()
{
while(~scanf("%d%d",&k,&m))
{
if(k>4){u=mul(qpow(b,k-4),c);
printf("%d\n",u.a[0][0]%m);}
else printf("%d\n",t[k]%m);
}
return 0;
}


奇怪的姿势一个个推,去掉两个mod就水过去了(AC)

#include<stdio.h>
int l,m,mm,mf,ff,fm,ta,tb,tc,td;
int main()
{
while(~scanf("%d%d",&l,&m))
{
if(l==1)printf("%d\n",2%m);
else if(l==0)printf("0\n");
else
{
mm=mf=fm=ff=1;
for(int i=2; i<l; i++)
{
ta=mm;
tb=mf;
tc=fm;
td=ff;
mm=(tc+ta)%m;
mf=ta;//mf=ta%m;
fm=(tb+td)%m;
ff=tb;//ff=tb%m;
}
printf("%d\n",(mm+mf+fm+ff)%m);
}
}
return 0;
}


奇怪的姿势两个两个推(AC)

 
#include<stdio.h>
int l,m;
int mm,mf,fm,ff;
int mma,mfa,fma,ffa;
int i;
int main()
{
while(~scanf("%d%d",&l,&m))
{
if(l==0)printf("0\n");
else
{
if(l%2){
i=1;
mm=1;mf=1;fm=0;ff=0;
}else{
mm=mf=fm=ff=1;
i=2;
}
for(; i<l; i+=2)
{
mma=mm,mfa=mf,fma=fm,ffa=ff;
mm=(mfa+ffa+fma+mma)%m;
mf=(fma+mma)%m;
fm=(mma+mfa)%m;
ff=mma%m;
}
printf("%d\n",(mm+mf+fm+ff)%m);
}
}
return 0;
}


漂亮的直接推(AC)

M(1 <= M <= 30) ,所以只在计算到大于一个比较大的数时才取模,这样可以减少取模的次数。这是参考了别人的代码。

#include<stdio.h>

int l,m;
int f[1000005]={0,2,4,6,9};

int main()
{
while(~scanf("%d%d",&l,&m))
{
for(int i=5;i<=l;i++){

f[i]=f[i-1]+f[i-3]+f[i-4];

if(f[i]>1000000)
f[i]%=m;
}
printf("%d\n",f[l]%m);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: