HDU3519 Lucky Coins Sequence(矩阵幂)

Lucky Coins Sequence

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 835    Accepted Submission(s): 437


Problem Description
As we all know,every coin has two sides,with one side facing up and another side facing down.Now,We consider two coins's state is same if they both facing up or down.If we have N coins and put them in a line,all of us know that it will be 2^N different ways.We call a "N coins sequence" as a Lucky Coins Sequence only if there exists more than two continuous coins's state are same.How many different Lucky Coins Sequences exist?
 

Input
There will be sevaral test cases.For each test case,the first line is only a positive integer n,which means n coins put in a line.Also,n not exceed 10^9.
 

Output
You should output the ways of lucky coins sequences exist with n coins ,but the answer will be very large,so you just output the answer module 10007.
 

Sample Input
3 4
 

Sample Output
2 6
 
题意:给你n个硬币,问你存在连续相同(正面or反面)长度>2的排列数

思路:令a(n)代表合法的个数,b(n)代表末两位不同,C(n)代表末两位相同。于是我们有如下递推关系式:

a(n)=2*a(n-1)+C(n-1);

b(n)=b(n-1)+C(n-1);

C(n)=b(n-1);

从而根据上式得出矩阵:

[2,0,1]   [a(n-1)]     [a(n)]

[0,1,1]   [b(n-1)]  =  [b(n)]

[0,1,0]   [C(n-1)]     [C(n)]

从而矩阵快速幂求出a(n).

代码:
#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<iostream>
#include<math.h>
using namespace std;
const int mod = 10007;
int sz = 3;
struct Matrix
{
    int mat[3][3];
};
Matrix mul(Matrix a,Matrix b)
{
    Matrix ret;
    for(int i=0;i<sz;i++)
      for(int j=0;j<sz;j++)
      {
          ret.mat[i][j]=0;
          for(int k=0;k<sz;k++)
            ret.mat[i][j] = (ret.mat[i][j] + (a.mat[i][k]*b.mat[k][j])%mod)%mod;
      }
    return ret;
}
Matrix pow_M(Matrix a,int n)
{
    Matrix ret;
    memset(ret.mat,0,sizeof(ret.mat));
    for(int i=0;i<sz;i++)ret.mat[i][i]=1;
    Matrix temp=a;
    while(n)
    {
        if(n&1)ret=mul(ret,temp);
        temp=mul(temp,temp);
        n>>=1;
    }
    return ret;
}
void show(Matrix a)
{
    printf("=======show========\n");
    for(int i=0; i<sz; i++)
    {
        for(int j=0; j<sz; j++)
            printf("%d ",a.mat[i][j]);
        printf("\n");
    }
}
int main()
{
    int n;
    while(scanf("%d",&n)!=EOF)
    {
        if(n<=2){puts("0");continue;}
        Matrix tt;
        memset(tt.mat,0,sizeof(tt.mat));
        tt.mat[0][2] = tt.mat[1][1] = tt.mat[1][2] = tt.mat[2][1] = 1;
        tt.mat[0][0]=2;
       // show(tt);
        Matrix temp = pow_M(tt,n-2);
       // show(temp);
        printf("%d\n",2*(temp.mat[0][1]+temp.mat[0][2])%mod);//初始 n=2 a(2)=0,b(2)=2,c(2)=2,与第一行相乘就是结果
    }
    return 0;
}
View Code
 
posted @ 2015-06-21 15:05  Doli  阅读(146)  评论(0)    收藏  举报