20180520模拟赛T3——chess

【问题描述】

小美很喜欢下象棋。

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

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

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

一开始\(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当场也没打出来的题。

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

时间: 2024-10-08 20:50:34

20180520模拟赛T3——chess的相关文章

体育成绩统计——20180801模拟赛T3

体育成绩统计 / Score 题目描述 正所谓“无体育,不清华”.为了更好地督促同学们进行体育锻炼,更加科学地对同学们进行评价,五道口体校的老师们在体育成绩的考核上可谓是煞费苦心.然而每到学期期末时,面对海量的原始数据,如何对数据进行处理,得到同学们的体育总评成绩却又成了体育部老师的一大难题. 对于大一的同学们来说,体育课的总评成绩由五部分组成:体育课专项成绩(满分50分).长跑测试成绩(满分20分).“阳光长跑”成绩(满分10分).体质测试成绩(满分10分).“大一专项计划”成绩(满分10分)

[10.5模拟赛]T3

T3 Description 小\(Z\)是\(ZRP(Zombies' Republic of Poetry\),僵尸诗歌共和国\()\)的一名诗歌爱好者,最近他研究起了诗词音律的问题. 在过去,诗词是需要编成曲子唱出来的,比如下面这首<菩萨蛮>,唱出来的话其对应的音符就是这样的: 南园满地堆轻絮, 愁闻一霎清明雨 1 1 5 5 6 6 5 4 4 3 3 2 2 1 因而可以发现,"1 1 5 5 6 6 5 4 4 3 3 2 2 1" 这串音符就成为了研究音律的

字符串模拟赛T3

只看我的做法就够了 #include<iostream> #include<cstdio> #include<string> #include<cstring> #include<algorithm> #include<vector> #include<queue> #include<stack> using namespace std; const int maxn = 1005; int n,m,ans;

[模拟赛] T3 最优序列

Description 给出一个长度为n(n<=1000)的正整数序列,求一个子序列,使得原序列中任意长度为m的子串中被选出的元素不超过k(k<=m<=10)个,并且选出的元素之和最大. Input 第一行三个数n,m,k. 第二行n个数,表示各元素数值大小. Output 一个数,表示最大元素和. Range 对于10%的数据,n<=10 对于30%的数据,n<=100 对于100%的数据,n<=1000, m从1到10随机(10的情况比较多) Solution 看范

[模拟赛] T3 Exploit

Description 4X概念体系,是指在PC战略游戏中一种相当普及和成熟的系统概念,得名自4个同样以"EX"为开头的英语单词. eXplore(探索) eXpand(拓张与发展) eXploit(经营与开发) eXterminate(征服) --维基百科 今次我们着重考虑exploit部分,并将其模型简化: 你驾驶着一台带有钻头(初始能力值w)的飞船,按既定路线依次飞过n个星球. 星球笼统的分为2类:资源型和维修型.(p为钻头当前能力值) 1.资源型:含矿物质量a[i],若选择开采

20180520模拟赛T1——math

[问题描述] 小美有 n 个点 m 条边. 让你给每个点一个正整数编号. 每条边有两个属性,相连的两个点的编号的 GCD 和 LCM. 题目保证整张图连通. 让你构造出一个编号. [输入格式] 从文件 math.in 中读入数据. 第一行两个正整数 n 和 m. 接下去m行每行 4 个正整数 xi,yi,gcdi,lcmi. [输出格式] 输出到文件 math.out 中. 如果是有解: 第一行一行 YES. 第二行 n 个数字表示编号. 否则输出一行NO. [样例] [样例输入] 1 0 [样

20180524模拟赛T3——Word

[题目描述] 有一个星球要创造新的单词,单词有一些条件: 字母集有\(p\)个元音和\(q\)个辅音,单词由字母构成 每个单词最多有\(n\)个元音和\(n\)个辅音(同一元音或辅音可重复使用) 每个单词中元音总是出现在所有辅音之前,可以没有元音或没有辅音 每个单词至少有一个字母 可以在字母上标记重音.元音中最多标记一个,辅音中也最多标记一个,一个单词中最多标记两个字母为重音 如果两个单词字母.字母顺序或者重音不同就认为这两个单词不同. 他们想要知道一共能创造多少不同的单词,由于答案可能很大,所

20180610模拟赛T3——书本整理

[问题描述] 小明的书架上放了许多书,为了使书架变得整洁,小明决定整理书架,他将所有书按高度大小排列,这样排了之后虽然整齐了许多,但小明发现,书本的宽度不同,导致书架看上去还是有些凌乱.小明把这个凌乱值定义为相邻两本书的宽度差的绝对值的和. 例如有4本书: 1×2 5×3 2×4 3×1 那么小明将其排列整齐后的顺序是: 1×2 2×4 3×1 5×3 凌乱值就是2+3+2=7. 于是小明决定拿掉其中的k本书,使凌乱值最小,你能帮他求出这个最小值吗?已知每本书的高度都不一样. [问题输入] 第一

树的dfs序,p1539,其他经典问题,2018/11/08模拟赛T3

树的dfs序指从根节点进行dfs(先序遍历),每次到达某个点的时间和离开这个点的时间.它可以将树上的问题转换成序列问题进行处理. 比如对于p1539的样例可以这样解释. 每个点的左边数字表示进入该点的"时间",右边的数字表示离开该点的"时间".对dfs序的介绍就到这里. 然后来看一个例题: 先读入边,跑一遍dfs确定dfs序. 对于操作1,把点x的进入的"时间"+=a,把x出去的"时间"-=a 这样操作3询问根节点到y的路径点