A Strange Dog called Vagaa II (矩阵相乘)

http://acm.hrbust.edu.cn/index.php?m=ProblemSet&a=showProblem&problem_id=1100

矩阵相乘法

A Strange Dog called Vagaa II

Time Limit: 1000 MS

Memory Limit: 65536 K

 

Total Submit: 105(32 users)

Total Accepted: 29(23 users)

Special Judge: No

 

Description

Leyni has a strange dog called Vagaa and it is just born.(We call it 0 years old.)

1.Vagaa will lay a small dog each year till it is 2 years old.(It will lay when it's 2 years old and won't lay when it's 3 years old.)
2.Vagaa will live forever.(Because it believes in ChunGe.)
3.The same as its child.(Its child will lay and live as the same as Vagaa.)

 

For example,
0 year : 1 dog. (Vagaa(0 years old).)
1 year : 2 dog. (Vagaa(1 years old) and its child(0 years old).)
2 year : 4 dog. (Vagaa(2) and its child(1) will lay 2 dogs(0).)
3 year : 7 dog. (Vagaa(3) won't lay. Its child(2) will lay 1 dog(0). The other 2 dogs(1) will lay 2 dogs(0).)
4 year : 12 dog. (...)

 

Now, Leyni want to know how many dogs he has in total when Vagaa is N years old.

Input

There are multiple test cases. The first line of input is an integer T indicating the number of test cases. Then T test cases follow.
For each test case:
Line 1. An Integer N.(0≤N≤109)

Output

For each test case:
Line 1. Output the number of dogs Leyni has in total MOD 10007.

Sample Input

5
0
1
2
3
4

Sample Output

1
2
4
7
12

Author

哈理工2011春季校赛

这道题目的递推公式就是a[n]=a[n-1]+a[n-2]+1;

类似于斐波那契数列。

但是数值比较大10^9个数是存不下来的。

故利用了矩阵相乘的便利。

来实现递推公式

代码:

#include<stdio.h>

#include<math.h>

int m=10007;

int A[1][3];

int B[3][3]={0,1,0,1,1,0,0,1,1};

int C[3][3];

void mul(int a[][3],int b[][3],int c[][3])

{//功能,求出a*b存在c里

    int i,j,h;

    for(i=0;i<3;i++)

     for(j=0;j<3;j++)

    {

       c[i][j]=0;

       for(h=0;h<3;h++)

         c[i][j]+=a[i][h]*b[h][j];

       c[i][j]%=m;

    }

}

void qiu(int x,int a[][3])//求出 B 的x次方,存在a里

{

    int i,j;

    int b[3][3];

    if(x==1)             //x等于1时,直接把B存在a里

    {

        for(i=0;i<3;i++)

         for(j=0;j<3;j++)

           a[i][j]=B[i][j];

        return;

    }

    if(x%2==0)

    {

        qiu(x/2,b);

        mul(b,b,a);

    }

    else

    {

        qiu(x-1,b);

        mul(b,B,a);

    }

}

int main()

{

    int c[3][3];

    int i,j,h,l,p,n,N;

    while(scanf("%d",&N) != EOF)

    while(N--)

    {

       scanf("%d",&p);

       //if(p==0)  printf("1\n");

       //else if(p==1) printf("2\n");

       //else if(p==2) printf("4\n");

      // else if(p==3) printf("7\n");

      // else

      // {

          A[0][0]=0;A[0][1]=1;A[0][2]=1;

          qiu(p+1, C);

          /*for(i=0; i<1; i++)

            for(j=0; j<3; j++)

            {

               c[i][j] = 0;

               for(h=0; h<3; h++)

               c[i][j] += A[i][h] * C[h][j];

               c[i][j] %= m;

            }*/

          mul(A,C,c);

          n = c[0][0] % m;

          printf("%d\n", n);

      // }

    }

    return 0;

}

再贴个小敏敏的代码:

#include <stdio.h>
#include <cstring>
using namespace std;

int A[3][3] = {0, 0, -1, 1, 0, 0, 0, 1, 2};
int B[3][3] = {1, 0, 0, 0, 1, 0, 0, 0, 1};
int C[3][3];

void mul(int a[3][3], int b[3][3], int c[3][3])
{
int i, j, k;
int f[3][3];

for(i = 0; i < 3; ++i)
for(j = 0; j < 3; ++j)
{
f[i][j] = 0;
for(k = 0; k < 3; ++k)
f[i][j] += a[i][k] * b[k][j];
//f[i][j] %= 10007;
if(f[i][j]>0) f[i][j]%=10007;
while(f[i][j]<0)f[i][j]+=10007;
}
for(i = 0; i < 3; ++i)
for(j = 0; j < 3; ++j)
c[i][j] = f[i][j];
}

void f(int arr[3][3], int n)
{
int a[3][3];
int i, j, k;
if(n == 0) return;
else if(n == 1)
{
for(i = 0; i < 3; ++i)
for(j = 0; j < 3; ++j)
C[i][j] = arr[i][j];
}
else if(n == 2)
{
mul(arr, arr, C);
return;
}
else
{
f(arr, n / 2);
for(i = 0; i < 3; ++i)
for(j = 0; j < 3; ++j)
a[i][j] = C[i][j];
mul(a, a, C);
if(n&1)
mul(arr, C, C);
/*if(n%2==0)
{
f(arr,n/2);
for(i = 0; i < 3; ++i)
for(j = 0; j < 3; ++j)
a[i][j] = C[i][j];
mul(a, a, C);
}
else
{
f(arr,n-1);
for(i = 0; i < 3; ++i)
for(j = 0; j < 3; ++j)
a[i][j] = C[i][j];
mul(a,arr,C);
}
*/
}
}


int main()
{
int t, n;
int m;
int sum;
int i, j, k;
int a[3] = {1, 2, 4};
int arr[3];
while(scanf("%d", &t) != EOF)
{
while(t--)
{
scanf("%d", &n);
if(n == 0)
printf("1\n");
else if(n == 1)
printf("2\n");
else if(n == 2)
printf("4\n");
else
{
f(A, n );
/* for(i = 0; i < 3; ++i)
{
for(j = 0; j < 3; ++j)
printf("%d ", C[i][j]);
printf("\n");
}
*/
memset(arr, 0, sizeof(arr));
for(j = 0; j < 3; j++)
for(k = 0; k < 3; k++)
{
arr[j] += a[k] * C[k][j];
arr[j] %= 10007;
}
arr[0] %= 10007;
printf("%d\n", arr[0]);
}
}
}
return 0;
}

这个的公式是用 a[n]=2*a[n-1]-a[n-3];

其实是一样的


 

原文地址:https://www.cnblogs.com/kuangbin/p/2412452.html