牛客练习赛87 E-贪吃蛇(矩阵快速幂)

传送门

题面:

题解:

考虑怎么吃最优,设\(l_1<l_2 <l_3.....\) ,那么先\(l_{n-1}\)\(l_n\) , 然后\(l_{n-2}\)\(l_{n-1}\) ,以此类推。

最后形成 \(t1>t2>t3>t4>......\) ,这样吃可以使得所有数都可以增长。

那么一共可以吃 \(m/x+1\) 次,即我们要模板上述过程\(m/x+1\) 次,显然时间复杂度不行

考虑构造一个矩阵:

\[\left[ \begin{matrix} l_1 & l_2 & l_3 ....\\ \end{matrix} \right] \times \left[ \begin{matrix} 0 & 0 & 0 ...&0 &1 \\ 0 & 0 & 0 ...&1&1 \\ &&&1&1\\ &0&1&1&1\\ 0&1&1&1&1\\ 1&1&1&1&1 \end{matrix} \right] = \left[ \begin{matrix} t_1 & t_2 & t_3 ....\\ \end{matrix} \right] \]

最后利用矩阵快速幂即可。

代码:

#pragma GCC diagnostic error "-std=c++11"
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<queue>
#include<map>
#include<stack>
#include<set>
#include<ctime>
#define iss ios::sync_with_stdio(false)
using namespace std;
typedef unsigned long long ull;
typedef long long ll;
typedef pair<int,int> pii;
const int mod=1e9+7;
const int MAXN=2e5+5;
const int inf=0x3f3f3f3f;
typedef vector<ll> vec;
typedef vector<vec> mat;
ll l[MAXN];
mat mul(mat& A, mat& B)
{
    mat C(A.size(), vec(B[0].size()));
    for (int i = 0; i < A.size(); i++) {
        for (int j = 0; j < B.size(); j++) {
            for (int k = 0; k < B[0].size(); k++) {
                C[i][k] = (C[i][k] + A[i][j] * B[j][k]%mod) % mod;
            }
        }
    }
    return C;
}
mat pow(mat A, ll n)
{
    mat B(A.size(), vec(A.size()));
    for (int i = 0; i < A.size(); i++) {
        B[i][i] = 1;
    }
    while (n > 0) {
        if (n & 1)
            B = mul(B, A);
        A = mul(A, A);
        n >>= 1;
    }
    return B;
}
int main()
{
    int t;
    scanf("%d", &t);
    while(t--)
    {
        int n, x, m;
        scanf("%d%d%d", &n, &x, &m);
        for (int i = 1; i <= n;i++)
        {
            scanf("%d", &l[i]);
        }
        sort(l + 1, l + 1 + n);
        m = m / x + 1;
        mat A(n, vec(n));
        for (int j = 0; j < n;j++)
        {
            for (int i =0; i < n;i++)
            {
                if(i<n-j-1)
                    A[i][j] = 0;
                else
                    A[i][j] = 1;
            }
        }
        cout << m << endl;
        A = pow(A, m);
        mat B(1, vec(n));
        for (int i = 0; i < n;i++)
            B[0][i] = l[i+1];
        mat ans = mul(B, A);
        printf("%lld\n", ans[0][n - 1]);
    }
}
posted @ 2021-08-22 11:40  TheBestQAQ  阅读(93)  评论(0)    收藏  举报