Codeforces Contest 1350&1349
CF1350
A Orac and Factors
我们发现如果 \(n\) 是偶数,则 \(f(n) = 2\),而它加上 \(2\) 之后还会是偶数,所以它只会一直加 \(2\),加 \(k\) 个 \(2\)。
如果它是奇数,则它不会有偶因数,所以它的最小因子一定是奇数。又因为奇数加奇数一定是偶数,所以我们可以暴力跑一遍(即 \(O(\sqrt{n})\) 枚举因子),然后就变成了上面那种情况。
大概就是这样了。
#include <iostream>
#include <cstdio>
using namespace std;
typedef long long ll;
ll t;
ll n, k, f;
ll Find(ll x) {
for (ll i = 2; i * i <= x; i++) {
if (x % i == 0) return i;
}
return x;
}
int main() {
cin >> t;
while (t--) {
cin >> n >> k;
f = Find(n);
if (f == 2) {
n += 2 * k;
} else {
n += f;
n += 2 * (k - 1);
}
cout << n << "\n";
}
return 0;
}
B Orac and Models
我来写一个思路基本和官方题解相同但又有一点不一样的题解。
也是 dp+枚举因数。
设计子状态 \(f[i]\) 待表选第 \(i\) 个数可以得到的最长序列。
转移方程就是对于每个 \(j | i\) 且 \(s[i]>s[j]\),\(f[i] = max(f[i], f[j]+1)\)。初始化所有 \(f\) 为 \(1\)。
注意这里的 \(j \neq i\)。
然后答案就是 \(max(f[i])\),\(i \in [1, n]\)。
这道题也是非常的水的。
#include <iostream>
#include <cstdio>
using namespace std;
int t;
int n;
int s[100010];
int f[100010], ans;
int main() {
cin >> t;
while (t--) {
ans = 0;
cin >> n;
for (int i = 1; i <= n; i++) f[i] = 1;
for (int i = 1; i <= n; i++) {
cin >> s[i];
}
for (int i = 1; i <= n; i++) {
if (i != 1) {
if (s[i] > s[1]) {
f[i] = max(f[i], f[1] + 1);
}
}
for (int j = 2; j * j <= i; j++) {
if (i % j) continue;
if (s[i] > s[j]) {
f[i] = max(f[i], f[j] + 1);
}
if (s[i] > s[i / j]) {
f[i] = max(f[i], f[i / j] + 1);
}
}
}
for (int i = 1; i <= n; i++) {
ans = max(ans, f[i]);
}
cout << ans << "\n";
}
return 0;
}
CF1349
B Orac and Medians
这道题其实就是几个美妙的性质。
首先如果序列里没有出现 \(k\),则一定是 \(no\)。
我们再证如果有两个连续的 \(k\) 出现,怎一定可以把另外两个相邻的数变成 \(k\),这样就可以把所有的数都变成 \(k\) 了。
如果一个 \(k\) 的旁边出现了一个比 \(k\) 大的数,那么 \(k\) 可以把它变成 \(k\),就成了上面那种情况。
所以我们现在就要让尽量多的大于等于 \(k\) 的数出现。
我们发现如果三个连续的数中有两个大于等于 \(k\) 的数,那么就可以把第三个数变成大于等于 \(k\) 的。所以如果存在三个数满足上述条件,则可以完成。
如果不存在呢?那用更多的数也凑不出比 \(k\) 大的,所以就不可能了。
#include <iostream>
#include <cstdio>
using namespace std;
int t;
int n, k;
int a[100010];
int main() {
cin >> t;
while (t--) {
cin >> n >> k;
bool flag = 0;
for (int i = 1; i <= n; i++) {
cin >> a[i];
if (a[i] == k) flag = 1;
if (a[i] >= k) a[i] = 1;
else a[i] = 0;
}
if (flag == 0) {
puts("no");
continue;
}
//特判n=1和n=2
if (n == 1) {
puts("yes");
continue;
}
if (n == 2) {
if (a[1] && a[2]) {
puts("yes");
} else {
puts("no");
}
continue;
}
bool ans = 0;
for (int i = 1; i + 2 <= n; i++) {
if (a[i] && (a[i + 1] || a[i + 2])) {
ans = 1;
break;
}
}
if (a[n - 1] && a[n]) ans = 1;
if (ans) puts("yes");
else puts("no");
}
return 0;
}