链接: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;
}
}
}