根据数据量猜解法
根据数据量猜解法
- 常数指令操作量 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 <= len(L) <= 18
1 <= len(R) <= 18
L
和R
是表示[1, 10^18)
范围的整数的字符串。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;
}
};