zoukankan      html  css  js  c++  java
  • 【FZU 1911】Construct a Matrix(矩阵快速幂+找规律)

    传送门:http://acm.fzu.edu.cn/problem.php?pid=1911

    题意:数列fn为斐波那契数列,sn为fn的前n项和,设r=sn%m,求一个r*r的矩阵,矩阵元素只能为0,-1,1使得矩阵每行每列的和没有重复。

    分析:我们知道fibonacci数列的前n项和S(n)=2*F(n)+F(n-1)-1,而本题中n的取值范围很大,所以求前n项和需要用矩阵快速幂。本题难点在于如何构造一个矩形满足题中条件。

    首先我们分析一下,显然当r为0时,我们构造不出来这样一个矩阵,所以矩阵不存在;当r为1时,无论这个格子填什么数,他所在的行和列的和一定相同。

    我们可以推广到r为奇数时,也必有一行和一列的和相等,所以当r==1||r&1时矩阵式不存在的。

    当r为偶数,假设r==6,此时共有12个和,范围是-6~6,其中共有6个奇数,7个偶数。我们先把矩阵初始化为-1,可知,每将一个-1变为0,就会使两个偶数和变为奇数和(当任意两个0不同行或同列时),

    所以至少要有3个不同行同列的-1变为0,才能使得和为6奇6偶。不妨假设现有矩阵为:

    -1 -1 -1 -1 -1 -1

    -1 -1 -1 -1 -1 -1

    -1 -1 -1 -1 -1 -1

     0 -1 -1 -1 -1 -1

    -1  0 -1 -1 -1 -1

    -1 -1  0 -1 -1 -1

    接下来我们就要构造3个0所在的行和列,使他们的和分别等于6个不同的奇数:

    -1 -1 -1

    -1 -1 -1

    -1 -1 -1

     0 -1 -1  1  1  1

     1  0 -1  1  1  1

     1  1  0  1  1  1

    这样,对于剩余的右上角的9个元素,我们只要填1和-1使得剩下的行和列的和为7个偶数中的任意6个即可(对称构造即可):

    -1 -1 -1 -1 -1  1

    -1 -1 -1 -1  1  1

    -1 -1 -1  1  1  1

     0 -1 -1  1  1  1

     1  0 -1  1  1  1

     1  1  0  1  1  1

    这样,一个满足条件的矩阵就构造出来了。

    总结:本题也属于思维大于算法和代码的题,难点在于如何去构造矩阵。

    代码如下:

    ///BY: Torrance_ZHANG
    #include <stdio.h>
    #include <iostream>
    #include <string.h>
    #include <math.h>
    #include <algorithm>
    #include <stack>
    #include <queue>
    #include <set>
    #include <map>
    using namespace std;
    int m, n;
    struct Matrix {
        int a[2][2];
        Matrix() {
            for (int i = 0; i < 2; i++)
                for (int j = 0; j < 2; j++)
                    a[i][j] = 0;
        }
        Matrix operator*(Matrix &p) {
            Matrix res;
            for (int i = 0; i < 2; i++) {
                for (int j = 0; j < 2; j++) {
                    res.a[i][j] = 0;
                    for (int k = 0; k < 2; k++) {
                        res.a[i][j] += (a[i][k] * p.a[k][j] % m);
                    }
                    res.a[i][j] %= m;
                }
            }
            return res;
        }
    } init, unit;
    void init_Matrix() {
        init.a[0][0] = 1;
        init.a[0][1] = 0;
        init.a[1][0] = 0;
        init.a[1][1] = 1;
        unit.a[0][0] = 1;
        unit.a[0][1] = 1;
        unit.a[1][0] = 1;
        unit.a[1][1] = 0;
    }
    Matrix Pow(Matrix x, Matrix y, int k) {
        while (k) {
            if (k & 1)
                y = y * x;
            x = x * x;
            k >>= 1;
        }
        return y;
    }
    void solve(int r) {
        printf("Yes
    ");
        int ans[205][205];
        memset(ans, -1, sizeof(ans));
        for (int i = r / 2 + 1; i <= r; i++)
            ans[i][i - (r / 2)] = 0;
        for (int i = r / 2 + 2; i <= r; i++)
            for (int j = 1; j <= (i - r / 2 - 1); j++)
                ans[i][j] = 1;
        for (int i = r / 2 + 1; i <= r; i++)
            for (int j = r - i + 1; j <= r; j++)
                ans[j][i] = 1;
        for (int i = 1; i <= r; i++) {
            for (int j = 1; j <= r; j++) {
                printf("%d", ans[i][j]);
                printf(j == r ? "
    " : " ");
            }
        }
    }
    int main() {
        int t, cas = 1;
        scanf("%d", &t);
        while (t--) {
            init_Matrix();
            scanf("%d%d", &n, &m);
            printf("Case %d: ", cas++);
            Matrix tmp = Pow(unit, init, n);
            //cout<<tmp.a[0][0]<<" "<<tmp.a[0][1]<<" "<<tmp.a[1][1]<<endl;
            int r = (tmp.a[0][1] * 2 + tmp.a[1][1] - 1) % m;
            //cout<<r<<endl;
            if (r == 0 || r & 1) {
                printf("No
    ");
                continue;
            } else solve(r);
        }
    }
  • 相关阅读:
    NFC
    精品收藏:GitHub人工智能AI开源项目
    typedef的用法,C语言typedef详解
    “此人不存在”
    视频换脸-Deepfakes代码解读和训练说明
    Linux下__attribute__((visibility ("default")))的使用
    piao
    高通开源android源码下载
    iOpenWorskSDK下载和答疑贴
    解构领域驱动设计(三):领域驱动设计
  • 原文地址:https://www.cnblogs.com/Torrance/p/5412802.html
Copyright © 2011-2022 走看看