对称与反对称

链接:https://www.nowcoder.com/acm/contest/94/H
来源:牛客网

对称与反对称
时间限制:C/C++ 2秒,其他语言4秒
空间限制:C/C++ 262144K,其他语言524288K
64bit IO Format: %lld
题目描述 
给出一个N*N的方阵A。构造方阵B,C:
使得A = B + C.其中 B为对称矩阵,C为反对称矩阵。
对于方阵S中的任意元素,若(S)ij = (S)ji,则称S为对称矩阵
对于方阵T中的任意元素,若(T)ij = -(T)ji,则称T为反对称矩阵
注意,所有运算在模M意义下

输入描述:
输入包含多组数据,处理到文件结束
每组数据,第一行包含两个正整数N,M(1 <= N <= 1000, 1 <= M <= 1000,000,001)分别表示方阵大小与模数,其中M必定为奇数。
接下来的N行,每行有N个非负整数,表示方阵A(0<=Aij<=1000,000,000)。
输出描述:
对于每组数据,将反对称矩阵$C$在$N$行中输出;
若不存在解,则输出"Impossible";
若存在多解,则输出任意解。
示例1
输入

2 19260817
0 1
1 0
输出

0 0
0 0

首先每一个n阶矩阵都可以写成一个对称矩阵和一个反对称矩阵的和,A=(A+AT)/2+(A-AT)/2;

(A+AT)/2为对称矩阵,(A-AT)/2为反对称矩阵。

所以要求的反对称矩阵的每个元素为 Xij=(Aij-Aji)/2 ;

题目要求运算在模M的意义下,因为要除以2,所以先找2 的逆元。求逆元:( 2*x与 1% m 同余。m为奇数,可以求出x (2的逆元)为(m+1)/2 )。负数的逆元:(负数%m+m)%m ;

#include<map>
#include<stack>
#include<queue>
#include<math.h>
#include<vector>
#include<string>
#include<stdio.h>
#include<iostream>
#include<string.h>
#include<algorithm>
#define maxn 1005
#define ll long long
#define inf 0x3f3f3f3f
using namespace std;
ll A[maxn][maxn];
ll B[maxn][maxn];
int main(){
    int n;ll m;
    while(cin>>n>>m){
        memset(A,0,sizeof(A));memset(B,0,sizeof(B));
        ll s=(m+1)/2;//求2的逆元。
        for(int i=0;i<n;i++){
            for(int j=0;j<n;j++)
                cin>>A[i][j];
        }
        for(int i=0;i<n;i++){
            for(int j=0;j<n;j++){
                if(i==j||A[i][j]==A[j][i])B[i][j]=B[j][i]=0;//主对角线都为0.
                else{
                    ll x=(((A[i][j]-A[j][i])*s)%m+m)%m;//可以直接求负数的逆元。
                    B[i][j]=x;
                }
            }
        }
        for(int i=0;i<n;i++){
            for(int j=0;j<n-1;j++){
                cout<<B[i][j]<<" ";
            }
            cout<<B[i][n-1]<<endl;
        }
    }
}









posted @ 2018-04-07 21:40  _大美  阅读(1172)  评论(0编辑  收藏  举报