A
签到。
值得注意的是,log2 是以2为底的对数,log10 是以10为底的对数,所以 log 就是ln 了,直接输出 150 * log(n) 即可。
B
签到,找准除法的细节。
C
记 n 的最高位是 pos 那么这个数字就是 1 << (pos + 1) - 1
最高位可以用 __lg(n) 来快速求得
void solve()
{
int n;
cin >> n;
cout << (1 << (__lg(n) + 1) - 1);
}D
注意到区间内包含1的 gcd的结果一定是1 所以想办法把需要的数字单独划分为一个区间,不需要的数字跟1放在一个区间 就行了
怎么是需要的数字呢?譬如,1101 需要的数字就是 1000, 100, 1
其实就是一个 lowbit
有一些数字是无法取得的,具体来说,因为 gcd 中 1是必然出现的, 所以所有偶数都不行;排列中全体数字的或也就是 (1 << (__lg(n) + 1) - 1 所以 m 超过这个数字也不行
具体代码可以参考下方:
void solve()
{
int n, m;
cin >> n >> m;
if (m % 2 == 0 or m >= (1ll << (__lg(n) + 1)))
{
cout << -1;
return;
}
auto pos = __lg(m);
auto mm = m;
vector<int> v;
int idx = 0;
while (mm)
{
if (mm & 1)
{
v.emplace_back(1ll << idx);
}
mm >>= 1;
idx++;
}
reverse(all(v));
map<int, int> mp;
for (auto num : v)
{
cout << num << ' ';
mp[num] = 1;
}
for (int i = 1; i <= n; i++)
{
if (!mp.count(i))
{
cout << i << ' ';
}
}
cout << endl;
cout << v.size() << endl;
for (int i = 0; i < v.size(); i++)
{
cout << i + 1 << ' ';
if (i + 1 == v.size())
{
cout << n;
}
else
{
cout << i + 1 << endl;
}
}
}E
可以考虑对所给表达式求导,令导数为0,然后对导数二分或者直接求解都可以。
这里着重讲一下三分。
二分法适用于给出单调函数,查找特定值;三分法适用于给出单峰函数,让求极值。
具体来说,我们给出 lmid = l + (r - l) / 3 rmid = r - (r - l) / 3 这就把整个区间划分成了三个部分
这之后 我们比较 和 的关系
对于求最小值:
- 如果 :最小值在右半部分,舍弃左半部分
- 如果 :最小值在左半部分,舍弃右半部分
然后不断重复这个过程即可 代码参考:
double f(double k, double e)
{
return 2 * k + 2 * e / pow(2, k);
}
void solve()
{
int n;
cin >> n;
double px, py;
cin >> px >> py;
double ans = 0.0;
const double eps = 1e-9;
for (int i = 0; i < n - 1; i++)
{
double x, y;
cin >> x >> y;
double e = sqrt(pow(x - px, 2) + pow(y - py, 2));
// 三分法求最小值
double l = 0.0, r = 100.0;
while (r - l > eps)
{
double lmid = l + (r - l) / 3;
double rmid = r - (r - l) / 3;
if (f(lmid, e) > f(rmid, e))
{
l = lmid;
}
else
{
r = rmid;
}
}
double k = (l + r) / 2;
ans += 2 * k + 2 * e / pow(2, k);
px = x;
py = y;
}
cout << ans;
}