CSUOJ 1313: ZZY的宠物

Description

ZZY领养了一对刚刚出生的不知名小宠物..巨萌巨可爱!!...小宠物的生命为5个单位时间并且不会在中间出意外翘辫子(如: 从0出生能活到5但活不到6)..小宠物经过2个单位时间成熟..刚刚成熟的一对小宠物能立即生育6只新的小宠物(如: 从0出生的一对在2时成熟并进行第一次生育)...小宠物是很忠诚的..不会在中途换伴侣..每对小宠物生育一次这一对的生育能力就会降低2个..也就是说一对小宠物在第二次生育时就只能生4个了..小宠物成熟后每个单位时间都会尽力的生育(例: 从0出生的一对..2时间生6个..3时间生4个..4时间生2个...5时间生不出..6时间这一对已经挂了..)..生育出来的新小宠物会继续这个过程.. 
ZZY想知道从单位时间0开始..经过M个单位时间(时间为M时)将有多少只活着的小宠物(0时刻有2只小宠物)
因为ZZY隐隐地觉得什么地方怪怪的...所以请将这个数目mod 10000 

Input

多组数据读到EOF
每组数据一行:  
M ( 0<=M<=2000000000 )
最多500组数据 

Output

每组输出一行为  Case 组号: 答案,即M时刻活着的小宠物个数%10000

Sample Input

012348

Sample Output

Case 1: 2Case 2: 2Case 3: 8Case 4: 12Case 5: 32Case 6: 528


根据题意建立这样一种数列 根据题意建立这样一种数列 根据题意建立这样一种数列 根据题意建立这样一种数列 根据题意建立这样一种数列 ,数列从 0号开始 号开始 .. 代表第 0个单 位时间出生的小宠物 位时间出生的小宠物 位时间出生的小宠物 位时间出生的小宠物 ...1 代表在第 1个单位时间出生的小宠物 个单位时间出生的小宠物 个单位时间出生的小宠物 个单位时间出生的小宠物 .. 以 此类推 .. 将这个数列某项称作 将这个数列某项称作 将这个数列某项称作 Z[x]
显然 .. 当 x>=5 时.. 在第 x天活着的小宠物数量 天活着的小宠物数量 天活着的小宠物数量 sum[x] = sum[x] = sum[x] = sum[x] = sum[x] = z[x -5] + z[x -4] + z[x -3] +z[x -2] +z[x -1] + z[x]
再看根据题意 再看根据题意 再看根据题意 再看根据题意 再看根据题意 再看根据题意 z[x] = x z[x] = x z[x] = xz[x] = z[x z[x] = x z[x] = x-2]/2*6 + z[x 2]/2*6 + z[x 2]/2*6 + z[x 2]/2*6 + z[x2]/2*6 + z[x 2]/2*6 + z[x 2]/2*6 + z[x-3]/2*4 + 3]/2*4 + 3]/2*4 + 3]/2*4 + 3]/2*4 + 3]/2*4 + z[x -4]/2*2 = z[x -2]*3 + z[x -3]*2 + z[x -4]
显然这个式 子是一递推的公显然这个式 子是一递推的公显然这个式 子是一递推的公显然这个式 子是一递推的公显然这个式 子是一递推的公显然这个式 子是一递推的公显然这个式 子是一递推的公显然这个式 子是一递推的公显然这个式 子是一递推的公显然这个式 子是一递推的公显然这个式 子是一递推的公显然这个式 子是一递推的公显然这个式 子是一递推的公显然这个式 子是一递推的公... 那么就可以用矩阵乘法来 那么就可以用矩阵乘法来 那么就可以用矩阵乘法来 那么就可以用矩阵乘法来 那么就可以用矩阵乘法来 那么就可以用矩阵乘法来 那么就可以用矩阵乘法来 那么就可以用矩阵乘法来 那么就可以用矩阵乘法来 那么就可以用矩阵乘法来 那么就可以用矩阵乘法来 求解这个递推公式的第 解这个递推公式的第 解这个递推公式的第 解这个递推公式的第 x项是多少 ... 观察数 列建立关于这个递推观察数 列建立关于这个递推观察数 列建立关于这个递推观察数 列建立关于这个递推观察数 列建立关于这个递推列的 "特征 “矩阵 ..
M = 0 1 0 0 0 0

       0 0 1 0 0 0

       0 0 0 1 0 0

       0 0 0 0 1 0

       0 0 0 0 0 1

       0 0 1 2 3 0


 而初始值为 0单位时间的出生情况 单位时间的出生情况 单位时间的出生情况 单位时间的出生情况 ... 可以自己递推出来 可以自己递推出来 可以自己递推出来 ... 为 A = { 0 , ,0 ,2 } 0 , ,0 ,2 } 0 , ,0 ,2 } 0 , ,0 ,2 } 0 , ,0 ,2 } 0 , ,0 ,2 } 0 , ,0 ,2 } 0 , ,0 ,2 } 0 , ,0 ,2 } 0 , ,0 ,2 }
要求第 x天出生了多少就用 天出生了多少就用 天出生了多少就用 z[x] = A*(M^x)... z[x] = A*(M^x)... z[x] = A*(M^x)...z[x] = A*(M^x)... z[x] = A*(M^x)... z[x] = A*(M^x)... z[x] = A*(M^x)... z[x] = A*(M^x)... z[x] = A*(M^x)... 矩阵乘法用 递归 2分来求解 分来求解 ... ...
要 求 sum(x)... 就分别求
出 z[x -5] ,z[x 5] ,z[x5] ,z[x 5] ,z[x -4] ,z[x 4] ,z[x4] ,z[x 4] ,z[x -3] ,z[x 3] ,z[x3] ,z[x 3] ,z[x -2] ,z[x 2] ,z[x2] ,z[x 2] ,z[x -1] ,z[x] 1] ,z[x]1] ,z[x] 1] ,z[x] 1] ,z[x]再将 这几个值加起来就行了 这几个值加起来就行了 这几个值加起来就行了 这几个值加起来就行了 ....


Code:

#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdio>
#define LL long long
using namespace std;
 
const int N = 52;
static int mod = 1111;
 
struct Matrix {
    int  mat[N][N]; //修改long long or int
    int n, m;
 
    Matrix() {//初始化,根据需要可以把此处删除!
        n = m = N;
        memset(mat, 0, sizeof(mat));
    }
 
    inline void init(int row, int column) {//初始矩阵大小
        n = row, m = column;
    }
 
    void init_e() {//初始化为单位矩阵
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < m; j++) {
                mat[i][j] = (i == j);
            }
        }
    }
 
    void print() {//测试检查用
        puts("——————————————");
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < m; j++) {
                printf("%d ", (int)mat[i][j]);
            }puts("");
        }puts("");
    }
 
};
 
//加法 重载运算符 +
Matrix operator + (Matrix a, Matrix b) {
    Matrix ret;
    ret.init(a.n, a.m);
    for (int i = 0; i < a.n; i++) {
        for (int j = 0; j < a.m; j++) {
            ret.mat[i][j] = a.mat[i][j] + b.mat[i][j];
            if (ret.mat[i][j] >= mod) {                    //这里的mod,没必要时要删除
                ret.mat[i][j] %= mod;
            }
        }
    }
    return ret;
}//加法
 
//n行m列  *  m行p列   =  n行p列 重载运算符 *
Matrix operator * (Matrix a, Matrix b) {
    Matrix ret;
    ret.init(a.n, b.m);
    for (int i = 0; i < a.n; i++) {
        for (int k = 0; k < a.m; k++) if (a.mat[i][k]) {
            for (int j = 0; j < b.m; j++) if (b.mat[k][j]) {
                ret.mat[i][j] = ret.mat[i][j] + a.mat[i][k] * b.mat[k][j];
                if (ret.mat[i][j] >= mod) {
                    ret.mat[i][j] %= mod;
                }//if
            }//for(j)
        }//for(k)
    }//for(i)
    return ret;
}//乘法
 
//求幂一般都是正方形矩阵,所以ret = a; 重载运算符 ^
Matrix operator ^ (Matrix a, int b) {
    Matrix ret = a,  tmp = a;
    ret.init_e();
    for ( ; b; b >>= 1) {
        if (b & 1) {
            ret = ret * tmp;
        }
        tmp = tmp * tmp;
    }
    return ret;
}//
 
//递归幂求和
//用二分法求矩阵和,递归实现,一般用下一种非递归版
Matrix Power_Sum1(Matrix a, int b) {
    Matrix ret = a;
    ret.init_e();
    if (b == 1) {
        return a;
    } else if (b & 1) {
        return (a ^ b) + Power_Sum1(a, b - 1);
    } else {
        return Power_Sum1(a, b >> 1) * ((a ^ (b >> 1)) + ret);
    }
}//Power_Sum1
 
//非递归幂求和
Matrix Power_Sum2(Matrix a, int b) {
    int k = 0 ,ss[32];
    Matrix tp1, tp2, ret;
    tp1 = tp2 = ret = a;
    ret.init_e();
    while (b) {
        ss[k++] = b & 1;
        b >>= 1;
    }
    for (int i = k - 2; i >= 0; i--) {
        tp1 = tp1 * (tp2 + ret);
        tp2 = tp2 * tp2;
        if (ss[i]) {
            tp2 = tp2 * a;
            tp1 = tp1 + tp2;
        }
    }
    return tp1;
}//Power_Sum2
 
int main()
{
    mod=10000;
    int M,cas=1;
    Matrix t0;
    t0.init(6,1);
    t0.mat[0][0]=2;
    for(int i=1;i<6;i++) t0.mat[i][0]=0;
    while(scanf("%d",&M)==1) {
        Matrix t;
        t.init(6,6);
        t.mat[0][0]=t.mat[0][4]=t.mat[0][5]=0;
        t.mat[0][1]=3; t.mat[0][2]=2; t.mat[0][3]=1;
        for(int i=1;i<6;i++) {
            for(int j=0;j<6;j++) t.mat[i][j]=(j==(i-1));
        }
        //t.print();
        if(M==0) {
            printf("Case %d: %d\n",cas++,(2%mod));
            continue;
        }
        t=t^M;
        Matrix ans=t0;
        ans=t*ans;
        LL sum=0;
        for(int i=0;i<6;i++) sum=(sum+ans.mat[i][0])%mod;
        printf("Case %d: %lld\n",cas++,sum);
    }
    return 0;
}
 
/**************************************************************
    Problem: 1313
    User: Roney
    Language: C++
    Result: Accepted
    Time:400 ms
    Memory:1484 kb
****************************************************************/



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章