2011-06-10 20:42:47Morris

d644. 壞脾氣小小皮

http://zerojudge.tw/ShowProblem?problemid=d644
內容 :

巫師小米是企鵝村首席巫師,也就是法力最強的巫師。
但是小米的召喚獸(每個巫師都有一個各不相同的召喚獸)是一隻海豹,
而且是一隻…脾氣很差的海豹!
因為這隻海豹脾氣很差,和小米的弟弟小皮一樣,
所以小米給這隻海豹取名叫做小小皮。

小小皮每天會跟小米一起練功,
但是小米練功狂太嚴重了……
所以每練一段時間得到的經驗值會因為情緒暴躁而減少。
如果用數列從第一天開始表示小小皮的經驗值會是:
第n天1 , 2 , 3 , 4 , 5 , 6 , 7 , 8  , 9
f(n) 1 , 1 , 2 , 2 , 4 , 6 , 9 , 15 , 24 ...
從第三天開始,經驗值是前兩天相加的和。
但是每逢3x+1(x正整數)的天數(第四天開始),經驗值-1!
(以上表為例,逢4、7天需要-1)

小米沒日沒夜的練功,
他已經搞不清楚小小皮現在的練得怎麼樣了,
請你寫個程式幫幫他好嗎?

輸入說明 :

每個測資點僅一筆測資,不需EOF結束。
每個測資只有一個正整數n(1<=n<=2147483647),代表要求的天數。

輸出說明 :

對於第n天小小皮的經驗值,請輸出其mod100019的值

範例輸入 :

10

範例輸出 :

38

提示 :

共計三個測資點,配分30%、35%、35%

出處 :

jack1 (管理:jack1)



作法描述 by (leopan0922)
經過觀察
答案會是fib(n)-fib(n-1)/2;
測資到int_max
所以又要用D&C
/**********************************************************************************/
/*  Problem: d644 "壞脾氣小小皮" from jack1                                 */
/*  Language: C                                                                   */
/*  Result: AC (4ms, 264KB) on ZeroJudge                                          */
/*  Author: morris1028 at 2011-06-06 09:06:13                                     */
/**********************************************************************************/


#include<stdio.h>
typedef struct {
    long long t[2][2];
}Matrix;
Matrix in, I2, o, init;
Matrix mult(Matrix x, Matrix  y) {
    Matrix t = o;
    int i, j, k;
    for(i = 0; i < 2; i++)
        for(j = 0; j < 2; j++)
            for(k = 0; k < 2; k++) {
                t.t[i][k] += x.t[i][j]*y.t[j][k] %100019;
                t.t[i][k] %= 100019;
            }
    return t;
}
long long ans(int n) {
    Matrix x = I2, y = init;
    while(n) {
        if(n&1) x = mult(x, y);
        y = mult(y, y);
        n /= 2;
    }
    return x.t[1][0];
}
main() {
    int n, a, b;
    for(a = 0; a < 2; a++)
        for(b = 0; b < 2; b++)
            in.t[a][b] = 0, I2.t[a][b] = 0,
            o.t[a][b] = 0, init.t[a][b] = 0;
    for(a = 0; a < 2; a++) I2.t[a][a] = 1;
    init.t[0][0] = init.t[0][1] = 1;
    init.t[1][0] = 1;
    while(scanf("%d", &n) == 1) {
        printf("%d\n", (ans(n) - ans(n-1)/2 + 100019)%100019);
    }
    return 0;
}

上一篇:d643. 勞動的符咒

下一篇:d645. 輪下亡魂