码迷,mamicode.com
首页 > 其他好文 > 详细

20180520模拟赛T3——chess

时间:2018-05-26 21:25:01      阅读:211      评论:0      收藏:0      [点我收藏+]

标签:数据   缺点   数据验证   接下来   一个   def   space   图片   http   

【问题描述】

小美很喜欢下象棋。

而且她特别喜欢象棋中的马。

她觉得马的跳跃方式很独特。(以日字格的方式跳跃)

小芳给了小美一张很大的棋盘,这个棋盘是一个无穷的笛卡尔坐标。

一开始\(time=0\)的时候,马在原点。每个时刻马都跳一步。

可是这个坐标图有点残缺,有几个点是不能跳到的。

然后小美很好奇在\(time=[0,K]\)中,马能跳到多少个不同的格子。

【输入格式】

从文件chess.in中读入数据。

第一行两个数K,n表示时间上限和残缺的点的数量。

接下来n行,每行一个坐标 xi,yi 表示一个残缺点的坐标。

【输出格式】

输出到文件chess.out中。

第一行输出一个数字表示答案。由于这个数字会很大,你需要输出他模 1000000007 。

【样例输入】

1 0

【样例输出】

9

【样例输入】

2 7
-1 2
1 2
2 1
2 -1
1 -2
-1 -2
-2 -1

【样例输出】

9

【数据规模】

对于\(30\%\)的数据\(K\le 500\)

对于\(100\%\)的数据\(0\le K \le 10^{18}, 0\le n\le 440, |xi|\le10, |yi|\le 10\)

【来源】

CF 57E

题解

一道神奇的乱搞题。

首先,对于一个oier,最基本的技能是暴力,于是我们先用bfs打一个暴力(代码下面会有)。

于是就拿到了37分的好成绩。

技术分享图片

但是除了大暴力,我们似乎并没有什么路可走——因为情况非常复杂。

那么这题为什么这么复杂?

因为有这句话:可是这个坐标图有点残缺,有几个点是不能跳到的。

于是我们想到简化:那这句话不在会怎么样?

我们发现一时找不出规律,但我们可以打张表。

#include <cstdio>
#include <queue>

using namespace std;

int mp[2003][2003];
int ans[6000];//ans[i]:第i步所到新到达的地方

int dirx[] = {1, 1, -1, -1, 2, 2, -2, -2};
int diry[] = {2, -2, 2, -2, 1, -1, 1, -1};

struct sxd
{
    int x, y;
};

queue<sxd> Q;

int n;
long long k;
long long cnt;

inline void bfs(int x, int y)
{
    mp[x][y] = 1;
    Q.push((sxd){x, y});
    while(!Q.empty())
    {
        sxd tmp = Q.front();
        Q.pop();
        ans[mp[tmp.x][tmp.y]]++;
        if(mp[tmp.x][tmp.y] > 70)
            break;
        for(int i = 0; i < 8; ++i)
        {
            int tx = tmp.x + dirx[i];
            int ty = tmp.y + diry[i];
            if(mp[tx][ty]) continue;
            mp[tx][ty] = mp[tmp.x][tmp.y] + 1;
            Q.push((sxd){tx, ty});
        }
    }
}

int main()
{
    bfs(1001, 1001);
    for(int i = 1; i <= 60; ++i)
        printf("%d,", ans[i]);
    return 0;
}

运行结果:

1,8,32,68,96,120,148,176,204,232,260,288,316,344,372,400,428,456,484,512,540,568,596,624,652,680,708,736,764,792,820,848,876,904,932,960,988,1016,1044,1072,1100,1128,1156,1184,1212,1240,1268,1296,1324,1352,1380,1408,1436,1464,1492,1520,1548,1576,1604,1632,

发现了什么?(并没有发现什么)到了后面项,该数列竟趋向于一个等差数列!

printf("%d,", ans[i]);改成printf("%d,", ans[i+1]-ans[i]);会更清晰:

7,24,36,28,24,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,

然后我们就可以大胆猜想了……

我们发现数据规模中\(|xi|, |yi|\)的值很小,是不是这样就不怎么会影响等差数列的波动幅度?

于是我们需要验证一下

//前面只是把if(mp[tmp.x][tmp.y] > 70)改成了if(mp[tmp.x][tmp.y] > 200)

int main()
{
    bfs(1001, 1001);
    cin >> n;
    for(int i = 1, x, y; i <= n; ++i)
    {
        cin >> x >> y;
        x += 1001;
        y += 1001;
        mp[x][y] = 1;//这样做还是挺妙的,把残缺坐标直接看成已访问
    }
    for(int i = 1; i <= 150; ++i)//输出多一些,让结论更可信
        printf("%d,", ans[i+1] - ans[i]);
    return 0;
}

随便造组数据验证一下:

8
2 3
1 2
2 1
5 6
-1 -2
-2 -1
-3 -4
-3 -2

输出

7,24,36,28,24,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,

经过多次验证,我们就可以很方便地想到正解:先暴力搜索几步(似乎都是选择500步的),然后用等差数列直接求出答案。

于是代码如下

//前面的bfs都差不多,就在写一遍了。

signed main()
{
    fin >> k >> n;//由于当时是模拟赛所以用了文件流
    for(int i = 1, x, y; i <= n; ++i)
    {
        fin >> x >> y;
        x += 1001;
        y += 1001;
        mp[x][y] = 1;
    }
    bfs(1001, 1001);
    if(k < 500)
    {
        for(int i = 1; i <= k+1; ++i)
            cnt = (cnt+ans[i])%mod;
        fout << cnt << endl;
    }
    else
    {
        long long inc = ans[500] - ans[499];//等差数列的公差
        k -= 498;
        k %= mod;
        for(int i = 0; i <= 499; ++i)
            cnt = (cnt+ans[i])%mod;
        fout << (((k*ans[500]%mod+cnt)%mod+(k*(k-1)>>1)%mod*inc%mod)%mod+mod)%mod << endl;
    }
    return 0;
}

最后,恭喜你打出了一道tourist当场也没打出来的题。

20180520模拟赛T3——chess

标签:数据   缺点   数据验证   接下来   一个   def   space   图片   http   

原文地址:https://www.cnblogs.com/pfypfy/p/9094182.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!