P1707 刷題比賽

$ \color{#0066ff}{ 題目描述 }$

洛谷OJ固然算是好地方,nodgd同窗打算和朋友分享一下。因而他就拉上了他的朋友Ciocio和Nicole兩位同窗一塊兒刷題。喜歡比賽的他們固然不放過這樣一次刷題比賽的機會!node

在第1天nodgd,Coicoi,Nicole都只作了1道題。c++

在第2天nodgd,Coicoi,Nicole都只作了3道題。git

他們都有着嚴格的刷題規則,而且會在每一天都很遵照規則的刷必定量的題。this

(1)nodgd同窗第k+2天刷題數量a[k+2]=p*a[k+1]+q*a[k]+b[k+1]+c[k+1]+r*k^2+t*k+1;spa

(2)Ciocio同窗第k+2天刷題數量b[k+2]=u*b[k+1]+v*b[k]+a[k+1]+c[k+1]+w^k;code

(3)Nicole同窗第k+2天刷題數量c[k+2]=x*c[k+1]+y*c[k]+a[k+1]+b[k+1]+z^k+k+2;blog

(以上的字母p,q,r,t,u,v,w,x,y,z都是給定的常數,並保證是正整數)ci

因而他們開始了長時間的刷題比賽!一共進行了N天(4<=N<=10^16)get

可是時間是難得的,nodgd想快速知道第N天每一個人的刷題數量。不過nodgd同窗還有大量的數學競賽題、物理競賽題、英語競賽題、美術競賽題、體育競賽題……要作,就拜託你來幫他算算了。數學

因爲結果很大,輸出結果mod K的值便可。

\(\color{#0066ff}{輸入格式}\)

第一行兩個正整數N,K。(4<=N<=10^16,2<=K<=10^16)

第二行四個正整數p,q,r,t。

第三行三個正整數u,v,w。

第四行三個正整數x,y,z。

(保證p,q,r,t,u,v,w,x,y,z都是不超過100的正整數)

\(\color{#0066ff}{輸出格式}\)

共三行,每行一個名字+一個空格+一個整數。依次是nodgd,Ciocio,Nicole和他們在第N天刷題數量mod K的值。

\(\color{#0066ff}{輸入樣例}\)

4 10007
2 1 1 1
2 2 3
1 1 2

\(\color{#0066ff}{輸出樣例}\)

nodgd 74
Ciocio 80
Nicole 59

\(\color{#0066ff}{數據範圍與提示}\)

矩陣乘法。

注意,中間相乘過程可能會比64位長整型的數據範圍還要大。

\(\color{#0066ff}{題解}\)

啊啊啊啊噁心!!

沒啥可說的,推矩陣(退役)吧

注意轉移要龜乘!

矩陣位置對應\(a[k+1],a[k],b[k+1],b[k],c[k+1],c[k],k^2,k,1,w^k,z^k\)

蜜汁轉移。。。

初始矩陣就是\(3,1,3,1,3,1,1,1,1,w,z\)

#include<bits/stdc++.h>
#define LL long long
LL in() {
    char ch; LL x = 0, f = 1;
    while(!isdigit(ch = getchar()))(ch == '-') && (f = -f);
    for(x = ch ^ 48; isdigit(ch = getchar()); x = (x << 1) + (x << 3) + (ch ^ 48));
    return x * f;
}
LL n, mod;
LL msc(LL x, LL y) {
    LL re = 0;
    while(y) {
        if(y & 1) re = (re + x) % mod;
        x = (x + x) % mod;
        y >>= 1;
    }
    return re;
}

struct node {
    LL ju[15][15];
    node() { memset(ju, 0, sizeof ju); }
    void e() {
        memset(ju, 0, sizeof ju);
        for(int i = 1; i <= 11; i++) ju[i][i] = 1;
    }
    friend node operator * (const node &a, const node &b) {
        node t;
        for(int i = 1; i <= 11; i++)
            for(int j = 1; j <= 11; j++)
                for(int k = 1; k <= 11; k++)
                    (t.ju[i][j] += msc(a.ju[i][k], b.ju[k][j])) %= mod;
        return t;
    }
    node ksm(LL y) {
        node re, x = *this;
        re.e();
        while(y) {
            if(y & 1) re = re * x;
            x = x * x;
            y >>= 1;
        }
        return re;
    }
}beg, A;
int tmp[12][12] = {
    {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
    {0, 0, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0},
    {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 
    {0, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0},
    {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
    {0, 1, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0},
    {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
    {0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0},
    {0, 0, 0, 0, 0, 1, 0, 2, 1, 0, 0, 0},
    {0, 1, 0, 0, 0, 2, 0, 1, 1, 1, 0, 0},
    {0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0},
    {0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0},
};
int lsbeg[] = {0, 3, 1, 3, 1, 3, 1, 1, 1, 1, 0, 0};

int main() {
    n = in(), mod = in();
    LL w, z;
    tmp[1][1] = in();  //p
    tmp[2][1] = in();  //q
    tmp[7][1] = in();  //r
    tmp[8][1] = in();  //t
    tmp[3][3] = in();  //u
    tmp[4][3] = in();  //v
    w = tmp[10][10] = in();//w
    tmp[5][5] = in();  //x
    tmp[6][5] = in();  //y
    z = tmp[11][11] = in();//z
    lsbeg[10] = w, lsbeg[11] = z;
    for(int i = 1; i <= 11; i++) beg.ju[1][i] = lsbeg[i];
    for(int i = 1; i <= 11; i++)
        for(int j = 1; j <= 11; j++)
            A.ju[i][j] = tmp[i][j];
    beg = beg * A.ksm(n - 2);
    printf("nodgd %lld\nCiocio %lld\nNicole %lld\n", beg.ju[1][1], beg.ju[1][3], beg.ju[1][5]);
    return 0;
}
相關文章
相關標籤/搜索