模拟赛总结

来源:互联网 发布:tcp 发送syslog java 编辑:程序博客网 时间:2024/06/18 00:15

题目 1
题目 2
题目 2 数据规模

1 棋盘
看上去很简单对不对?直接记录有哪些行和列已经会被攻击,然后计算一下剩下的就好了(怎么算?这么简单自己想= =)。

2 图
是不是跟 NOIP 信息传递特别像?直接”DFS“一下就好了,然后考虑用倍增计算走过的最小值。。。
不好意思,这么做会超时。既然都想到了倍增,为什么不直接倍增呢?由于题目中给定的图具有可以不停走的性质,因此我们可以强行倍增,让走的次数达到k次就好了。

不对吧。。。坑死人的模拟题就这么短的题解?连参考代码都没有一个?

因为今天我要谈的,是有关数据的问题。

1 棋盘
对于 100% 的数据,n105,那算到最后,是不是int装不下?于是我就这么定义了一下:

typedef long long INT;int n, m; //输入在int范围内bool row[maxn], colum[maxn];INT rUsed, cUsed;

沿着“正难则反”的道路,我选择了计算已经被用过的方块,最后用总块数去减(不要问我为什么不直接算= =虽然正面还要简单些)。然而,我却选择了这样输出答案:

INT ans = n * n - ((rUsed + cUsed) * n - rUsed * cUsed);cout << ans << endl;

没什么问题么?然而:
n * n

成功地爆炸了。。。

所以说,如果题目中有可能有超出int范围的数据,在空间允许的情况下,尽量使用long long。如果可能,最好在除了循环变量的其它地方进行统一。

2 图

这道题将面临一个新的问题:如何输出。由于这道题输出量比较大,使用cout进行输出有点吃力,而printf输出长整形的时候可能会遇到跨平台问题(最扯的是lemon,同一个编译器,它偏偏只支持%I64d。所以还是得自己写输出函数。。。)

inline void printOut(INT x) //自己去简化,只有当输出量极大时才建议加上:写错了会得不偿失{    if (!x)    {        putchar('0');        return;    }    bool minus = x < 0;    if (minus) x = -x;    char temp[20] = { 0 };    int length = 0;    while (x)    {        temp[length++] = x % 10 + '0';        x /= 10;    }    if (minus)    {        temp[length++] = '-';    }    while (true)    {        putchar(temp[--length]);        if (!length) return;    }}

更可怕的是计算2k时极易出错。一般来说,计算2k时使用1 << k便足矣。然而,这道题的k最多要计算到233。这时,绝对不要使用1 << k,而应当使用:

1ll << k

这里建议:计算2k时,先写成1ll,就算不可能超出范围,也可以稍后来改。千万不要为了省下类型转换的时间把分丢掉。

强烈建议全局大INT。 Orz