根据数据量猜解法

根据数据量猜解法

  • 常数指令操作量 10^7 ~ 10^8,以此来猜测自己设计的算法有没有可能在规定时间内通过

消灭怪物

  • 全排列
#include <vector>
#include <iostream>

using namespace std;

int res;
vector<pair<int, int>> arr;

// [0, curIndex) 是已经使用的技能
void generate(int n, int blood, int curIndex, int steps) {
    // 击杀怪物
    if (blood <= 0) {
        res = min(res, steps);
        return;
    }
    // 杀不掉,就不要更新 res
    if (curIndex == n) return;
    // 尝试剩下的每一个技能
    for (int i = curIndex; i < n; ++i) {
        // 减去相应血量
        int damage = (arr[i].first < blood) ? arr[i].second : arr[i].second * 2;
        blood -= damage;
        // 移到前面,[0, curIndex] 是已经使用的技能
        swap(arr[i], arr[curIndex]);
        // 递归处理子问题
        generate(n, blood, curIndex + 1, steps + 1);
        // 回溯
        blood += damage;
        swap(arr[i], arr[curIndex]);
    }
}

int main() {
    arr.resize(10);
    int times;
    cin >> times;
    for (int n, blood; times > 0; times--) {
        cin >> n >> blood;
        res = 0x7fffffff;
        // 输入技能
        for (int i = 0; i < n; ++i)
            cin >> arr[i].second >> arr[i].first;
        generate(n, blood, 0, 0);
        if (res == 0x7fffffff) res = -1;
        cout << res << endl;
    }
}

9. 回文数

  • 转换成字符串
#include <string>

using namespace std;

class Solution {
public:
    bool isPalindrome(int x) {
        // 题目规定负数不回文
        if (x < 0) return false;
        // 转换成逆序字符串
        string str;
        while (x > 0) {
            // 追加上个位
            str += x % 10;
            x /= 10;
        }
        int left = 0;
        int right = str.length() - 1;
        while (left < right) {
            if (str[left] != str[right]) return false;
            left++;
            right--;
        }
        return true;
    }
};
  • 计算总位数,根据位数计算首位数字
#include <valarray>

using namespace std;

class Solution {
public:
    bool isPalindrome(int x) {
        if (x < 0) return false;
        // 先计算数字有多少位
        int len = 0;
        for (int i = x; i > 0; i /= 10) len++;
        // 需要判断 len / 2 对数字
        for (int offset = 0; offset < len / 2; offset++) {
            int left = (x / (int) (pow(10, len - offset - 1))) % 10;
            int right = (x / (int) (pow(10, offset))) % 10;
            if (left != right) return false;
        }
        return true;
    }
};
  • 计算偏移,根据偏移计算首位数字
using namespace std;

class Solution {
public:
    bool isPalindrome(int x) {
        if (x < 0) return false;
        int offset = 1;
        // 计算偏移,有 n 位,则偏移量为 pow(10, n-1)
        while (x / offset >= 10)
            offset *= 10;
        while (x != 0) {
            if (x / offset != x % 10) return false;
            // 去除第一位和最后一位的数字
            x = (x % offset) / 10;
            offset /= 100;
        }
        return true;
    }
};

906. 超级回文数

  1. 1 <= len(L) <= 18
  2. 1 <= len(R) <= 18
  3. LR 是表示 [1, 10^18) 范围的整数的字符串。
  4. int(L) <= int(R)
  • 方案一:先判断平方根是否是回文,然后再判断自己是否是回文。遍历的是平方根,数据量缩小到 10^9

  • 超时

#include <vector>
#include <iostream>
#include <string>
#include <valarray>

using namespace std;

class Solution {
public:
    bool isPalindrome(long long x) {
        if (x < 0) return false;
        long long offset = 1;
        // 计算偏移,有 n 位,则偏移量为 pow(10, n-1)
        while (x / offset >= 10)
            offset *= 10;
        while (x != 0) {
            if (x / offset != x % 10) return false;
            // 去除第一位和最后一位的数字
            x = (x % offset) / 10;
            offset /= 100;
        }
        return true;
    }

    long long getNumber(string nums) {
        long long res = 0;
        for (int i = 0; i < nums.length(); ++i)
            res = res * 10 + nums[i] - '0';
        return res;
    }

    int superpalindromesInRange(string left, string right) {
        long long l = getNumber(left);
        long long r = getNumber(right);
        // 找到大于等于 l 的第一个有平方根的数的平方根
        long long start;
        if (pow((long long) sqrt(l), 2) == l) {
            start = (long long) sqrt(l);
        } else {
            start = (long long) sqrt(l) + 1;
        }
        // 找到小于等于 r 的第一个有平方根的数
        long long end = (long long) sqrt(r);

        int res = 0;
        // 平方后不超过 r 的情况下
        for (long long cur = start; cur <= end; cur++)
            // 自身回文,且平方后也回文
            if (isPalindrome(cur) && isPalindrome(cur * cur))
                res++;
        return res;
    }
};
  • 方案二:根据种子生成一个回文数,再判断这个回文数的平方是否回文。遍历的是种子,数据量缩小到 10^5
#include <vector>
#include <iostream>
#include <string>
#include <valarray>

using namespace std;

class Solution {
public:
    // 判断回文
    bool isPalindrome(long long x) {
        long long offset = 1;
        // 计算偏移,有 n 位,则偏移量为 pow(10, n-1)
        while (x / offset >= 10)
            offset *= 10;
        while (x != 0) {
            if (x / offset != x % 10) return false;
            // 去除第一位和最后一位的数字
            x = (x % offset) / 10;
            offset /= 100;
        }
        return true;
    }

    // 解析数字
    long long parse(string nums) {
        long long res = 0;
        for (int i = 0; i < nums.length(); ++i)
            res = res * 10 + nums[i] - '0';
        return res;
    }

    // 生成两种回文数,123 生成 12321、123321
    pair<long long, long long> generate(int x) {
        long long first = x, second = x;
        for (int i = x / 10; i > 0; i /= 10)
            first = first * 10 + i % 10;
        for (int i = x; i > 0; i /= 10)
            second = second * 10 + i % 10;
        return make_pair(first, second);
    }

    // 判断回文数平方根 q 是否在平方根的范围 [start, end] 内,且平方后也是回文
    bool check(int start, int end, int q) {
        if ((q >= start && q <= end)
            && isPalindrome((long long) q * q))
            return true;
        return false;
    }

    int superpalindromesInRange(string left, string right) {
        long long l = parse(left);
        long long r = parse(right);
        // 找到大于等于 l 的第一个有平方根的数的平方根
        long long start;
        if (pow((long long) sqrt(l), 2) == l) {
            start = (long long) sqrt(l);
        } else {
            start = (long long) sqrt(l) + 1;
        }
        // 找到小于等于 r 的第一个有平方根的数
        long long end = (long long) sqrt(r);

        int res = 0;
        for (int seed = 1; seed < 1e5; ++seed) {
            auto item = generate(seed);
            // 加快一点常数时间
            if (item.first > end) break;
            // 加快一点常数时间
            if (item.second < start) continue;
            if (check(start, end, item.first)) res++;
            if (check(start, end, item.second)) res++;
        }
        return res;
    }
};
posted @ 2024-10-07 11:08  n1ce2cv  阅读(7)  评论(0编辑  收藏  举报