对称与反对称
链接: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; } } }