其实标题我想写“心得体会与题解”的,后来,看着自己只有一道题ac,……

今天学长发来一个链接说有华南理工的校赛,本来今天要做gym的比赛来着,就先做这个了,

看着首页赫然写着

本次比赛难度跨度大,既适合0基础经过一个学期学习并至少掌握C++或JAVA进行编程的同学,也适合在区域赛取得奖项的同学。

然而看到题之后,慌得要死,因为从头看到尾一个我能做的都没有。甚至前半个小时左右,没有一个人提交代码。

正当自己慌慌张张还有点失望的时候,看见了一道题星星点点的有人通过,还挺多的……

于是在瞎开一题始终过不去的情况下换了这道题(我瞎开的题到现在为止还是0人通过)

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

首先,朋友推出来一个公式,

t[i][j]=(a[i][j]-a[j][i])/2;

推导过程:A[i][j]=S[i][j]+T[i][j];

A[j][i]=S[i][j]-T[i][j];(因为A矩阵转置了,所以,加的位置不变,减的位置(T数组)应该转置一下也就是负的和正的互相颠倒)

上面两式相加,得

A[j][i]+A[i][j]=2S[i][j];

两式相减

A[i][j]+A[j][i]=2T[i][j]

证毕。

我拿到了这个公式,冷静了一下,开始上代码,先小数据范围跑一下,自己出了个数据验证了一下,验证出来这个公式是正确的。

后来,看题意要取模,我就拿出来昨天Wannafly的板子来取模(除以2就涉及到分数取模)

很快套完却发现过不了。之后就是漫长的debug……把所有的矩阵ABC全都输出了,确定计算过程没错!但是就是过不了……

这时已经找不出什么错误了,还是一样的焦急,已经过去两个半小时……突然跳出来一条提示:

“负数的取模要加上m之后,变成正数再取模,答案全是正数”

恍然大悟。赶紧改代码……奇迹发生!……emmm,能在过题人数如此稀少的比赛里过一道题真的很激动!!

好了,show you the code!!!

#include<bits/stdc++.h>
using namespace std;
long long int a[1010][1010],t[1010][1010];
double fsa[1010][1010],fsans[1010][1010];//这两个一个是保存小数据原始答案,一个保存那个正对称矩阵
int main()
{
    int n;long long m;
    while(scanf("%d%lld",&n,&m)!=EOF)
    {
        for(int i=0;i<n;i++)
        {
            for(int j=0;j<n;j++)
            {
                scanf("%lld",&a[i][j]);
            }
        }
        for(int i=0;i<n;i++)
        {
            for(int j=0;j<n;j++)
            {
                t[i][j]=(a[i][j]%m-a[j][i]%m);
                if(t[i][j]<0)t[i][j]+=m;
                fsa[i][j]=t[i][j]/2.0;
                fsans[i][j]=a[i][j]-fsa[i][j];
                long long int s=0,c,d;
                c=t[i][j];
                d=2;
                while((m*s+c)%d!=0)
                {
                    s++;
                }
                long long ans=(m*s+c);
                if(ans%d)ans+=(d-ans%d);
                t[i][j]=ans/d;
            }
        }
        for(int i=0;i<n;i++)
        {
            printf("%lld",t[i][0]);
            for(int j=1;j<n;j++)
            {
                printf(" %lld",t[i][j]%m);
            }
            printf("\n");
        }
    }
}

别的也就不多说了!还是自己实力不行,训练太少,思考太少!多多训练才是王道!

多打、敢打比赛,才能认清自己的不足!