• FZU 1692 Key problem


    FZU_1692

        首先感觉输入数据里面的L和R应该反过来读取即先读入R再读入L,要不然样例算不出来,不知道是不是我理解错题意了。

        矩阵不难构造,但这个题让进一步注意到了矩阵运算中的常熟优化:

        ①由于递推关系的矩阵各行是循环同构的,而两个这样的循环同构的矩阵的乘积依然是循环同构的,所以在用二分矩阵的方法计算的时候,可以先用O(N^2)的时间计算出第一行,再用O(N^2)的时间平移出下面各行的结果,这样每次做乘法的复杂度就由O(N^3)减少到了O(N^2)。

        ②矩阵乘法的multiply的函数最好使用引用传递传参,如果直接传参的话每次相当于把矩阵复制一遍,这样效率就比较低了。

    #include<stdio.h>
    #include<string.h>
    #define MAXD 110
    int N, M, L, R, D, a[MAXD];
    struct Matrix
    {
        int a[MAXD][MAXD];
        Matrix()
        {
            memset(a, 0, sizeof(a));
        }
        void init()
        {
            int i, j;
            for(i = 0; i < N; i ++)
                a[i][(i + N - 1) % N] = L, a[i][i] = 1, a[i][(i + 1) % N] = R;
        }
    };
    Matrix multiply(Matrix &x, Matrix &y)
    {
        int i, j, k;
        Matrix z;
        for(k = 0; k < N; k ++)
            if(x.a[0][k])
            {
                for(j = 0; j < N; j ++)
                    if(y.a[k][j])
                z.a[0][j] = (z.a[0][j] + (long long)x.a[0][k] * y.a[k][j]) % D;
            }
        for(i = 1; i < N; i ++)
        {
            z.a[i][0] = z.a[i - 1][N - 1];
            for(j = 1; j < N; j ++)
                z.a[i][j] = z.a[i - 1][j - 1];
        }
        return z;
    }
    Matrix powmod(Matrix unit, Matrix mat, int n)
    {
        while(n)
        {
            if(n & 1)
                unit = multiply(mat, unit);
            n >>= 1;
            mat = multiply(mat, mat);
        }
        return unit;
    }
    void solve()
    {
        int i, j, ans;
        Matrix unit, mat;
        scanf("%d%d%d%d%d", &N, &M, &R, &L, &D);
        for(i = 0; i < N; i ++)
        {
            scanf("%d", &a[i]);
            unit.a[i][i] = 1;
        }
        mat.init();
        unit = powmod(unit, mat, M);
        for(i = 0; i < N; i ++)
        {
            ans = 0;
            for(j = 0; j < N; j ++)
                if(unit.a[i][j] && a[j])
                    ans = (ans + (long long)unit.a[i][j] * a[j]) % D;
            if(i)
                printf(" ");
            printf("%d", ans);
        }
        printf("\n");
    }
    int main()
    {
        int t;
        scanf("%d", &t);
        while(t --)
        {
            solve();
        }
        return 0;
    }
  • 相关阅读:
    jar强退出 JVM报错:Failed to write core dump. Core dumps have been disabled.
    配置 DHCP Snooping 和 IPSG
    OpenOffice
    RabbitMQ ADD
    YAPI 接口管理
    mysql:1153 Got a packet bigger than ‘max_allowed_packet’ bytes的解决方法
    修改端口的VLAN
    阿里云OSS设置跨域访问
    seata连接nacos 报错
    Linux登录超时问题
  • 原文地址:https://www.cnblogs.com/staginner/p/2471017.html
Copyright © 2020-2023  润新知