嘘~ 正在从服务器偷取页面 . . .

洛谷P1707 刷题比赛 题解


洛谷P1707 刷题比赛 题解

题目链接:P1707 刷题比赛

题意

洛谷OJ当然算是好地方,nodgd 同学打算和朋友分享一下。于是他就拉上了他的朋友 Ciocio 和 Nicole 两位同学一起刷题。喜欢比赛的他们当然不放过这样一次刷题比赛的机会!

在第 $1$ 天 nodgd,Coicoi,Nicole 都只做了 $1$ 道题。

在第 $2$ 天 nodgd,Coicoi,Nicole 都只做了 $3$ 道题。

他们都有着严格的刷题规则,并且会在每一天都很遵守规则的刷一定量的题。

  1. nodgd 同学第 $k+2$ 天刷题数量

  2. Ciocio 同学第 $k+2$ 天刷题数量

  3. Nicole 同学第 $k+2$ 天刷题数量

(以上的字母 $p,q,r,t,u,v,w,x,y,z$ 都是给定的常数,并保证是正整数)

于是他们开始了长时间的刷题比赛!一共进行了 $n$ 天。

但是时间是可贵的,nodgd 想快速知道第 $n$ 天每个人的刷题数量。

不过 nodgd 同学还有大量的数学竞赛题、物理竞赛题、英语竞赛题、美术竞赛题、体育竞赛题…… 要做,就拜托你来帮他算算了。

由于结果很大,输出结果 $\bmod \space m$ 的值即可。

输入格式

第一行两个正整数 $n,m$。

第二行四个正整数 $p,q,r,t$。

第三行三个正整数 $u,v,w$。

第四行三个正整数 $x,y,z$。

输出格式

共三行,每行一个名字 + 一个空格 + 一个整数。

依次是 nodgd,Ciocio,Nicole 和他们在第 $n$ 天刷题数量 $\bmod \space m$ 的值。

数据范围

$4\le n \le 10^{16},~2\le m \le 10^{16},~1\le p,q,r,t,u,v,w,x,y,z \le 100$。

我一看,啊,又是大模数,又是离谱大的矩阵快速幂,纯属搞人心态的。

不急,我们一个个来看。首先可以发现里面有些简单的,例如 $pa_{k+1}$ 这种,直接加进初始矩阵就好。

然后就是 $w^k,z^k$ 这种。我们可以直接在矩阵里面 $w^k \times w = w^{k+1}$ 。

可能最难的就是 $k^2$ 了吧,其实也不难,因为有 $(k + 1) ^ 2 = k^2 + 2k + 1$ ,所以只要稍微弄下就好了

考虑构建递推矩阵:(初始矩阵为 $k=1$ 时)

转移矩阵如下:

我们只需要求一下 $A \times M^{n-1}$ 就好啦,别忘了这个模数太大需要用 __int128 优化哦~

时间复杂度 $\mathcal{O}(11^3\times \log n)$

代码:(最优解 34ms 可以吹一下的

#include <bits/stdc++.h>
using namespace std;
#define int long long
#define INF 0x3f3f3f3f3f3f3f3f
typedef vector< vector<int> > mat;
int mod;
void up(int &x,int y) { x < y ? x = y : 0; }
void down(int &x,int y) { x > y ? x = y : 0; }
void add(int &x,int y) { (x += y) >= mod ? x -= mod : x; }
#define N ((int)())

int qpow(int a,int b)
{
    int ans = 1; for(; b; b >>= 1)
    {
        if(b & 1) ans = (__int128)ans * a % mod;
        a = (__int128)a * a % mod;
    }
    return ans;
}
mat mul(mat A, mat B)
{
    int n = A.size(), m = A[0].size(), p = B[0].size();
    mat C(n, vector<int>(p));
    for(int i = 0; i < n; i++)
        for(int j = 0; j < p; j++)
        {
            __int128 t = 0;
            for(int k = 0; k < m; k++) t += (__int128)A[i][k] * B[k][j];
            add(C[i][j], t % mod);
        }
    return C;
}
mat qpow(mat A, int b)
{
    int n = max(A.size(), A[0].size());
    mat ans(n, vector<int>(n));
    for(int i = 0; i < n; i++) ans[i][i] = 1;
    for(; b; b >>= 1)
    {
        if(b & 1) ans = mul(ans, A);
        A = mul(A, A);
    }
    return ans;
}
mat M(11, vector<int>(11)), A(1,vector<int>(11));
signed main()
{
    ios::sync_with_stdio(0);
    cin.tie(0);cout.tie(0);
    // freopen("check.in","r",stdin);
    // freopen("check.out","w",stdout);
    int n,p,q,r,t,u,v,w,x,y,z; cin >> n >> mod; 
    cin >> p >> q >> r >> t >> u >> v >> w >> x >> y >> z;
    A[0][0] = A[0][1] = A[0][2] = 3; A[0][3] = A[0][4] = A[0][5] = 1;
    A[0][6] = A[0][7] = A[0][8] = 1; A[0][9] = w; A[0][10] = z;
    M[0][0] = p; M[0][1] = 1; M[0][2] = 1; M[0][3] = 1;
    M[1][0] = 1; M[1][1] = u; M[1][2] = 1; M[1][4] = 1;
    M[2][0] = 1; M[2][1] = 1; M[2][2] = x; M[2][5] = 1;
    M[3][0] = q;
    M[4][1] = v;
    M[5][2] = y;
    M[6][0] = r; M[6][6] = 1;
    M[7][0] = t; M[7][2] = 1; M[7][6] = 2; M[7][7] = 1;
    M[8][0] = 1; M[8][2] = 2; M[8][6] = 1; M[8][7] = 1; M[8][8] = 1; 
    M[9][1] = 1; M[9][9] = w;
    M[10][2] = 1; M[10][10] = z;
    mat res = mul(A, qpow(M, n - 1));
    cout << "nodgd " << res[0][3] << '\n';
    cout << "Ciocio " << res[0][4] << '\n';
    cout << "Nicole " << res[0][5] << '\n';
    return 0;
}

文章作者: q779
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-ND 4.0 许可协议。转载请注明来源 q779 !
评论
  目录