在下头很铁之HDU-6253

今天下午闲来无事(其实有很多作业没写但是就是不想写),又怂的一B不敢和喜欢的人聊天,可能是年少时把勇气都用光了吧。

所以还不如刷刷题,于是刷着刷着我就练就了举世无双的武功:铁头功。

BB了这么多,给个链接,我的小宝贝自己看看题吧,让这题搞得我铁头已虚。


题目链接:HDU-6253

题目大意:在一个无限大的棋盘里面玩游戏,你初始的时候有一匹马,问你经过k步,马的可能涉足的位置有哪些。

看看样例:


直觉告诉我们:这题一定有规律啊啊啊啊。因而,打表+猜结论+AC。(我只是没想到我的步骤多了一步,打表+猜结论+头铁+AC)。

打表的程序(递归时间复杂度O(8^n),欢迎有更好的打表方式来打我脸):

#include<bits/stdc++.h>
using namespace std;
int a[2000][2000];
void f(int i, int x, int y){
    a[x][y] = 1;
    if (i == 0)
        return ;
    i--;
    f(i,x-1, y-2);
    f(i,x-2, y-1);
    f(i,x-2, y+1);
    f(i,x-1, y+2);
    f(i,x+1, y+2);
    f(i,x+2, y+1);
    f(i,x+2, y-1);
    f(i,x+1, y-2);
}
int main(){
    for (int i = 1; i <= 10; i ++){
        memset(a, 0, sizeof(a));
        a[1000][1000] = 1;
        f(i, 1000, 1000);
        int ans = 0;
        for (int j = 0; j < 2000; j ++){
            for (int k = 0; k < 2000; k ++){
                if (a[j][k] == 1)
                    ans ++;
            }
        }
        cout << ans << "*" << endl;
    }

    return 0;
}


打表结果:

(时间是真jier长啊)

整理一下,找规律(这个考验个人的数学素养了):


看到了吧?

然后验算如下:

特殊情况特殊处理(0, 1, 2, 3, 4);

从第五个开始,易得如下关系式:a[i+1] = 2*a[i] - a[i-1] + 28, a[4] = 205, a[5] = 325, i >=5;

即转化成求a[n]的过程(高中求数列的通项公式)。

移项:a[i+1]-a[i] = a[i] - a[i-1] + 28 ……①;

b[i+1] = a[i+1]-a[i], 故b[i] = a[i]-a[i-1].

①式为:b[i+1] = b[i] + 28, b[5] = 120, b[6] = 148, i >= 5;

b是等差数列,已知b[n] = b[5] + 28*(n-5);

b[n] = 28*n - 20;

a[j] - a[j-1] =b[j] = 28*j -20;

a[5]-a[4] = 28*5 - 20;

a[6]-a[5] = 28*6 - 20;

……

a[n]-a[n-1] = 28*n - 20;

相加:

a[n] - a[4] = 28*(5+n)(n-5+1) - 20*(n-1);

整理得:a[n] = 14*n*n - 6*n + 5, n >= 5;

 (还好高中认真学习过哈哈哈哈哈)

所以代码就搞出来啦:

#include <cstdio>
#include <iostream>
using namespace std;

int main() {
    int T;
    scanf("%d", &T);
    int cou = 1;
    while(T--){
        unsigned long long n;///注意long long 会wa,头铁王
        cin >> n;
        printf("Case #%d: ", cou++);
        if (n == 0)
            printf("%d\n", 1);
        if (n == 1)
            printf("%d\n", 9);
        if (n == 2)
            printf("%d\n", 41);
        if (n == 3)
            printf("%d\n", 109);
        if (n == 4)
            printf("%d\n", 205);
        if (n >= 5){
            cout << 14 * n * n - 6 * n + 5 << endl;
        }
    }
    return 0;
}


注意:上面的注释!!这就是我wa的原因:

我们注意到n的最大值是10^9,故最后的结果最大值可能为:14*10^9*10^9=1.4*10^19,超过了long long的数据范围,but没超过unsigned long long 的范围,这里我们再回忆一下数据的范围:

(详情见点我呀点我呀~

最后,吃一堑长一智,再贴个图见证一下我头铁的历程:



写完了,说点不正经的:

夜很深,我抚摸着它黑色的身体

就像软软的你的肚子

吸一口,缓缓地吐出

这潮湿的暧昧

然后轻轻地吻在你的小腹

像一个萤火虫

钻进茂密而繁盛的森林

寻找属于你的最深的海底

渴望在那里遇见另一个月亮

牛奶一样的月色

洪流般的涌向你

可是这思念的猛兽

早已将借着这夜色

将我重重击倒

我打开窗

夜很深,我无法触碰她的身体。

2018年4月15日晚23:58



评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值