链接:
来源:牛客网 给出一个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<=A
ij
<=1000,000,000)。
输出描述:
对于每组数据,将反对称矩阵$C$在$N$行中输出; 若不存在解,则输出"Impossible"; 若存在多解,则输出任意解。 (注意最后的输出全为非负数)
示例1
输入
2 192608170 11 0
输出
0 00 0 公式很好推 c[i][j] = (a[i][j] - a[j][i]) / 2; 主要是除以二的时候会除不整,所以要用逆元。 可以说是一道逆元的模板题了。 附ac代码:
1 #include2 #include 3 #include 4 #include 5 #include 6 #include 7 #include 8 using namespace std; 9 typedef long long ll;10 const int maxn = 1111;11 ll a[maxn][maxn], c[maxn][maxn];12 ll exgcd(ll a, ll b, ll& x, ll &y) {13 ll d = a;14 if(b != 0) {15 d = exgcd(b, a % b, y, x);16 y -= (a / b) * x;17 18 } else {19 x = 1; y = 0;20 }21 return d;22 }23 ll getm(ll a, ll m) {24 ll x, y;25 exgcd(a, m, x, y);26 return (m + x % m) % m;27 }28 int main() {29 int n;30 ll m;31 while(~scanf("%d %lld", &n, &m)) {32 for(int i = 1; i <= n; ++i) {33 for(int j = 1; j <= n; ++j) {34 scanf("%lld", &a[i][j]);35 }36 }37 ll mm = getm(ll(2), m);38 // printf("%lld mmm\n",mm);39 for(int i = 1; i <= n; ++i) {40 for(int j = 1; j <= n; ++j) {41 c[i][j] = ((a[i][j] - a[j][i]) * mm) % m;42 if(c[i][j] < 0) c[i][j] += m;43 }44 }45 for(int i = 1; i <= n; ++i) {46 for(int j = 1; j <= n; ++j) {47 if(j == 1) printf("%lld", c[i][j]);48 else printf(" %lld", c[i][j]);49 }50 printf("\n");51 }52 }53 return 0;54 }