佳佳的 Fibonacci

题目描述 

佳佳对数学,尤其对数列十分感兴趣。在研究完Fibonacci数列后,他创造出许多稀奇古怪的数列。例如用S(n)表示Fibonacci前n项和\bmod mmodm的值,即S(n)=(F_1+F_2+...+F_n) \bmod mS(n)=(F1+F2+...+Fn)modm,其中F_1=F_2=1,F_i=F_{i-1}+F_{i-2}F1=F2=1,Fi=Fi1+Fi2。可这对佳佳来说还是小菜一碟。
终于,她找到了一个自己解决不了的问题。用T(n)=(F_1+2F_2+3F_3+...+nF_n) \bmod mT(n)=(F1+2F2+3F3+...+nFn)modm表示Fibonacci数列前n项变形后的和\bmod mmodm的值。
现在佳佳告诉你了一个n和m,请求出T(n)的值。

输入描述:

输入数据包括一行,两个用空格隔开的整数n,m。

输出描述:

仅一行,T(n)的值。
示例1

输入

复制
5 5

输出

复制
1

说明

T(5)=(1+2 \times1+3 \times2+4 \times3+5 \times5) \bmod5=1T(5)=(1+2×1+3×2+4×3+5×5)mod5=1

备注:

对于30 \%30%的数据,1 \leq n \leq10001n1000;
对于60 \%60%的数据,1 \leq m \leq10001m1000;
对于100 \%100%的数据,1 \leq n,m \leq 2^{31}-11n,m2311。


/*   S(n) = F(n + 2) - 1
T(n) = F(1) + 2F(2) + ... + nF(n)
= nS(n) - (n - 1)F(1) - (n - 2)F(2) - ... - F(n - 1)
= nS(n) - (S(1) + S(2) + ... + S(n - 1))
= nS(n) - (F(3) - 1 + F(4) - 1 + ... + F(n + 1) - 1)
= nS(n) - (F(3) + F(4) + ... + F(n + 1) - n + 1)
= nS(n) - (F(3) + F(4) + ... + F(n + 1)) + n - 1
= n(F(n + 2) - 1) - (F(3) + F(4) + ... + F(n + 1)) + n - 1
= n(F(n + 2) - 1) - (F(1) + F(2) + ... + F(n + 1)) + n - 1 + F(1) + F(2)
= nS(n) - S(n + 1) + n - 1 + F(1) + F(2)
= n(F(n + 2) - 1) - (F(n + 3) - 1) + n - 1 + F(1) + F(2)
= n(F(n + 2) - 1) - (F(n + 3) - 1) + n + 1
= nF(n + 2) - n - F(n + 3) + 1 + n + 1
= nF(n + 2) - F(n + 3) + 2
*/
#include<bits/stdc++.h>
using namespace std;
void mul(int f[2], int a[2][2], int mod) {
    int c[2];
    memset(c, 0, sizeof(c));
    for (int i = 0; i < 2; i++) {
        for (int j = 0; j < 2; j++) {
            c[i] = (c[i] + (long long)f[j] * a[j][i]) % mod;
        }
    }
    memcpy(f, c, sizeof(c));
}
void mulself(int a[2][2], int mod) {
    int c[2][2];
    memset(c, 0, sizeof(c));
    for (int i = 0; i < 2; i++) {
        for (int j = 0; j < 2; j++) {
            for (int k = 0; k < 2; k++) {
                c[i][j] = (c[i][j] + (long long)a[i][k] * a[k][j]) % mod;
            }
        }
    }
    memcpy(a, c, sizeof(c));
}
int main() {
    int a[2][2] = {{0, 1}, {1, 1}};
    int f[2] = {0, 1};
    int aa[2][2] = {{0, 1}, {1, 1}};
    int ff[2] = {0, 1};
    int n, m;
    cin >> n >> m;
    int pa = n + 2, pb = n + 3;
    while (pa) {
        if (pa & 1) mul(f, a, m);
        mulself(a, m);
        pa >>= 1;
    }
    while (pb) {
        if (pb & 1) mul(ff, aa, m);
        mulself(aa, m);
        pb >>= 1;
    }
    cout << ((long long)n * f[0] - ff[0] + 2 + m) % m << endl;
    return 0;
}
posted @ 2020-07-21 20:40  HighLights  阅读(373)  评论(0)    收藏  举报