1 条题解

  • 0
    @ 2026-9-28 21:30:52

    前言:

    简单的矩阵乘法。

    ps:题目。

    思路:

    令原数和加密后的数构成一个矩阵,设矩阵 AA 为 [cisum−ci]\begin{bmatrix}c_i&sum-c_i\end{bmatrix},则加密一次后的矩阵 A′A' 为 $\begin{bmatrix}sum-c_i&(n-1)\times sum-(sum-c_i)\end{bmatrix}$,因为显而易见所有数加密一次后总和变为原来的 n−1n-1 倍。

    推出 AA 乘矩阵 [0n−11n−2]\begin{bmatrix}0&n-1\\1&n-2\end{bmatrix} 可以得到 A′A',设这个矩阵为 BB。

    按照这个规律,加密 TT 次和 T+1T+1 次构成的矩阵为 A×BTA\times B^T。

    对于每个数,处理出矩阵 AA,就可以用快速幂解决 A×BTA\times B^T,得到加密 TT 次的数。

    记住,不开 long long 见祖宗!!!

    代码:

    #include <bits/stdc++.h>
    #define MOD 98765431
    typedef long long lint;
    struct matrix
    {
        int x , y;
        lint num[3][3];
        matrix operator*(const matrix a) const
        {
            matrix t;
            int i , j , k;
            memset(t.num , 0 , sizeof(t.num));
            t.x = x , t.y = a.y;
            for(i = 1 ; i <= t.x ; i ++ )
                for(j = 1 ; j <= t.y ; j ++ )
                    for(k = 1 ; k <= y ; k ++ )
                        t.num[i][j] = (t.num[i][j] + num[i][k] * a.num[k][j]) % MOD;
            return t;
        }
    }a , b;
    lint c[50010];
    matrix qpow(matrix a , int b)
    {
        matrix t;
        int i;
        t.x = a.x , t.y = a.y;
        memset(t.num , 0 , sizeof(t.num));
        for(i = 1 ; i <= t.x ; i ++ )
            t.num[i][i] = 1;
        while(b)
        {
            if(b & 1)
                t = t * a;
            a = a * a;
            b >>= 1;
        }
        return t;
    }
    typedef long long LL;
    inline LL read()
    {
    	register LL x=0,f=1;
    	char c=getchar();
    	while(c<'0'||c>'9'){
    		if(c=='-') f=-1;
    		c=getchar();
    	}
    	while(c>='0'&&c<='9') x=(x<<3)+(x<<1)+(c^48),c=getchar();
    	return x*f;
    }
    
    int main()
    {
        int n , t , i;
        lint sum = 0;
        n=read(),t=read(); 
        for(i = 1 ; i <= n ; i ++ )
            c[i]=read() , sum = (sum + c[i]) % MOD;
        b.x = b.y = 2;
        b.num[1][1] = 0 , b.num[1][2] = n - 1 , b.num[2][1] = 1 , b.num[2][2] = n - 2;
        b = qpow(b , t);
        a.x = 1 , a.y = 2;
        for(i = 1 ; i <= n ; i ++ )
        {
            a.num[1][1] = c[i] , a.num[1][2] = (sum - c[i] + MOD) % MOD;
            printf("%lld\n" , (a * b).num[1][1]);
        }
        return 0;
    }//别问我为什么要加快输,因为我要最优解
    

    要看就看我的,我是最优解呢

    c++14 + O2 = 最优解。

    • 1

    信息

    ID
    2293
    时间
    1000ms
    内存
    128MiB
    难度
    10
    标签
    递交数
    8
    已通过
    5
    上传者