“景驰科技杯”2018年华南理工大学程序设计竞赛 H 对称与反对称

Description:

给出一个N*N的方阵A。构造方阵B,C:
使得A = B + C.其中 B为对称矩阵,C为反对称矩阵。
对于方阵S中的任意元素,若(S)ij = (S)ji,则称S为对称矩阵
对于方阵T中的任意元素,若(T)ij = -(T)ji,则称T为反对称矩阵
注意,所有运算在模M意义下

Input:

输入包含多组数据,处理到文件结束
每组数据,第一行包含两个正整数N,M(1 <= N <= 1000, 1 <= M <= 1000,000,001)分别表示方阵大小与模数,其中M必定为奇数。
接下来的N行,每行有N个非负整数,表示方阵A(0<=Aij<=1000,000,000)。

Output:

对于每组数据,将反对称矩阵 C C C N N N行中输出;
若不存在解,则输出"Impossible";
若存在多解,则输出任意解。

Sample Input:

2 19260817
0 1
1 0

Sample Output:

0 0
0 0

题目链接

矩阵主对角线不用考虑,先设A为:
[ <mstyle displaystyle="false" scriptlevel="0"> 0 </mstyle> <mstyle displaystyle="false" scriptlevel="0"> C 1 </mstyle> <mstyle displaystyle="false" scriptlevel="0"> C 2 </mstyle> <mstyle displaystyle="false" scriptlevel="0"> 0 </mstyle> ] \left[ \begin{matrix} 0 &amp; C1\\ C2 &amp; 0\\ \end{matrix} \right] [0C2C10]
设B为:
[ <mstyle displaystyle="false" scriptlevel="0"> 0 </mstyle> <mstyle displaystyle="false" scriptlevel="0"> x </mstyle> <mstyle displaystyle="false" scriptlevel="0"> x </mstyle> <mstyle displaystyle="false" scriptlevel="0"> 0 </mstyle> ] \left[ \begin{matrix} 0 &amp; x\\ x &amp; 0\\ \end{matrix} \right] [0xx0]
设C为:
[ <mstyle displaystyle="false" scriptlevel="0"> 0 </mstyle> <mstyle displaystyle="false" scriptlevel="0"> y </mstyle> <mstyle displaystyle="false" scriptlevel="0"> y </mstyle> <mstyle displaystyle="false" scriptlevel="0"> 0 </mstyle> ] \left[ \begin{matrix} 0 &amp; y\\ -y &amp; 0\\ \end{matrix} \right] [0yy0]
则可得公式:
( x + y ) % m = C 1 ( x y ) % m = C 2 (x+y)\%m=C1\\ (x-y)\%m=C2 (x+y)%m=C1(xy)%m=C2
化简可得
y = ( ( C 1 C 2 ) ÷ 2 ) % m y=((C1-C2)÷2)\%m y=((C1C2)÷2)%m
这里就得到了反对称矩阵C和输入矩阵A的关系式。
但是这个求解方程式中存在除法和取模的计算,这就需要用逆元来计算了。一篇解释逆元挺清楚的博文——>逆元(其实我理解的逆元就是在模关系下的倒数)。
求逆元又需要用到拓展欧几里得算法:

扩展欧几里德算法是用来在已知a, b求解一组x,y,使它们满足贝祖等式: ax+by = gcd(a, b) =d
——百度百科

拓展欧几里得算法模板:

// 返回值为d(=gcd(a, b)),和ax+by=d中的x,y
long long extendgcd(long long a, long long b, long long &x, long long &y) {
    if (a == 0 && b == 0) {
        return -1;
    }
    if (b == 0) {
        x = 1;
        y = 0;
        return a;
    }
    long long d = extendgcd(b, a % b, y, x);
    y -= a / b * x;
    return d;
}

求逆元模板:

// 返回值为a关于mod的逆元
long long inverse(long long a, long long mod) {
    long long x, y;
    long long d = extendgcd(a, mod, x, y);
    if (d == 1) {
        return (x % mod + mod) % mod;
    }
    else {
        return -1;
    }
}

输出中每行行尾无多余空格。

AC代码:

#include <bits/stdc++.h>
using namespace std;
#define mem(a,b) memset(a,b,sizeof(a))
typedef long long ll;
typedef pair<int, int> P;
const int INF = 0x3f3f3f3f;
const int maxn = 1e3+5;
const double eps = 1e-5;
const double e = 2.718281828459;

int n;
ll m;
ll A[maxn][maxn];
ll C[maxn][maxn];

ll extendgcd(ll a, ll b, ll &x, ll &y) {
    if (a == 0 && b == 0) {
        return -1;
    }
    if (b == 0) {
        x = 1;
        y = 0;
        return a;
    }
    ll d = extendgcd(b, a % b, y, x);
    y -= a / b * x;
    return d;
}

ll inverse(ll a, ll mod) {
    ll x, y;
    ll d = extendgcd(a, mod, x, y);
    if (d == 1) {
        return (x % mod + mod) % mod;
    }
    else {
        return -1;
    }
}

void antisymmetric_matrix() {
    ll inv = inverse(2, m);
    for (int i = 1; i <= n; ++i) {
        for (int j = 1; j <= n; ++j) {
            if (i < j) {
                C[i][j] = (A[i][j] - A[j][i]) * inv % m;
                C[j][i] = -C[i][j];
                while (C[i][j] < 0) {
                    C[i][j] += m;
                }
                while (C[j][i] < 0) {
                    C[j][i] += m;
                }
            }
        }
    }
}

int main() {
    ios::sync_with_stdio(0);
    cin.tie(0);
    while (cin >> n >> m) {
        mem(A, 0);
        mem(C, 0);
        for (int i = 1; i <= n; ++i) {
            for (int j = 1; j <= n; ++j) {
                cin >> A[i][j];
            }
        }
        antisymmetric_matrix();
        for (int i = 1; i <= n; ++i) {
            for (int j = 1; j <= n; ++j) {
                cout << C[i][j];
                if (j != n) {
                    cout << " ";
                }
            }
            cout << endl;
        }
    }
    return 0;
}

全部评论

相关推荐

阿里巴巴各部门年终奖开奖了,有人拿到了220w
真烦好烦真烦:拿命换钱呢,公司给你220万,肯定是因为你对公司的贡献大于220万,想想要多厉害多累才能达到
投递阿里巴巴集团等公司10个岗位 >
点赞 评论 收藏
分享
03-26 15:18
已编辑
华北水利水电大学 Java
点赞 评论 收藏
分享
小厂面经,也是我的处女面(30min)1.自我介绍2.spring&nbsp;boot的自动装配原理(好多类和接口的单词都忘了全称是啥了,就说了记得的单词,流程应该说对了吧)3.有用过redis吗?主要是用在实现什么功能(说了技术派用redis的zset来实现排行榜)5.有了解过Redisson吗?讲一下对于分布式锁的了解以及在什么场景下应用(说了秒杀场景)6.对mysql有了解吗?包括它的索引优化和创建(把想起来的全说了)7.了解设计模式吗?比如单例模式,为什么要使用单例模式,它的优点是什么(昨天刚看的设计模式)8.工厂模式有了解吗?主要的使用场景是?(也是昨天刚看的)9.场景题:有7个服务器,需要在早上十点定时的向数据库中的用户表中的用户发短信,如果做到发送的消息不重复,且如果发送失败了需要知道是到哪个用户失败了,这样下次就直接从这个用户开始(我答了用spring&nbsp;task来实现定时,用分布式锁来保证只有一份服务器可以发送消息,用消息队列来存储消息,然后用消息确认机制来保证错误信息的记录,以及在数据库或者业务层面完成消息消费的幂等性)10.场景题:如果在系统启动的时间就将数据库的所有用户相关的信息都读到一个hashmap中(这个没啥思路,没答好)27届的投了一个星期终于有一个面试了,大部分公司都只招26的
inari233:已oc,拒了
查看9道真题和解析
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客企业服务