Codeforces Round #686 (Div. 3)題解
A
題意:給你一個n,求一個長度為n的排列p,使得\(p[i]!=i\)
做法:reverse一下,然後如果n為奇數,那麼swap(p[1], p[(n+1)/2]);
#include <bits/stdc++.h> using namespace std; int main() { int t; scanf("%d", &t); while (t--) { int n; scanf("%d", &n); if (n & 1) { for (int i = 1; i <= n; i++) { if (i == 1) printf("%d ", (n + 1) / 2); else if (i == (n + 1) / 2) printf("%d ", n); else printf("%d ", n - i + 1); } } else for (int i = 1; i <= n; i++) printf("%d ", n - i + 1); puts(""); } return 0; }
B
題意:給一個長度為n的陣列a(1<=ai<=n),求其中只出現過一次的數中最小數的下標,沒有的話輸出-1
做法:把數字丟到桶裡,然後從小到大for一遍,找到最小的數的值,再在a中for一遍找出下標(這裡也可以用pos[i]表示值為i的數的下標,然後直接輸出)
注意,多測清空不要用memset,第一發被卡T了
#include <bits/stdc++.h> #define maxn 200005 int n, a[maxn], cnt[maxn]; int main() { int t; scanf("%d", &t); while (t--) { scanf("%d", &n); for (int i = 1; i <= n; i++) cnt[i] = 0; for (int i = 1; i <= n; i++) { scanf("%d", &a[i]); ++cnt[a[i]]; } int v; bool fl = 0; for (int i = 1; i <= n; i++) { if (cnt[i] == 1) { fl = 1; v = i; break; } } if (!fl) puts("-1"); else { for (int i = 1; i <= n; i++) if (a[i] == v) { printf("%d\n", i); break; } } } return 0; }
C
題意:好麻煩,自己看(
做法:開n個vector
對於vector[i]表示哪些下標的值為i,然後算一下空隙vector[i][j]與vector[i][j-1]之間有沒有元素,有的話cnt[i]++
最後\(ans=min_{1 \leq i \leq n}{cnt_i}\)
#include <bits/stdc++.h> #define maxn 200005 using namespace std; int n; vector<int> pos[maxn]; int main() { int t; scanf("%d", &t); while (t--) { scanf("%d", &n); for (int i = 1; i <= n; i++) pos[i].clear(); for (int i = 1; i <= n; i++) { int x; scanf("%d", &x); pos[x].push_back(i); } int ans = n; for (int i = 1; i <= n; i++) if (!pos[i].empty()) { int cnt = 0; for (int j = 1; j < pos[i].size(); j++) if (pos[i][j] - pos[i][j - 1] > 1) cnt++; ans = min(ans, cnt + (pos[i].front() != 1) + (pos[i].back() != n)); } printf("%d\n", ans); } return 0; }
D
題意:給你一個n,求出一個長度為k的序列a,使得\(\prod_{i=0}^k a_i = n\),且a[i]|a[i+1]且k最大(a[i]!=1)
做法:考慮n質因數分解後為\({p_1}^{e_1} {p_2}^{e_2}...{p_m}^{e_m}\)
則答案為\(e_mx=max_{1 \leq i \leq m}{e_i}\)
證明:
因為\(\prod_{i=0}^k a_i = n\),所以題目就相當於把n質因數分解後的每個值分配給a[1]~a[k]
因為a[i]|a[i+1],所以a[i+1]分到的每項一定是大於等於a[i]分到的
那肯定取等於最賺,但是你每次至少要分出來1。
所以答案不超過\(e_mx\)
你構造一個長度為\(e_mx\)的序列,使得a[1]~a[\(e_mx-1\)]都等於p_mx,a[\(e_mx\)]=剩下的數乘起來
這樣就構造除了長為\(e_mx\)的序列,完事
#include <bits/stdc++.h>
#define ll long long
using namespace std;
int main() {
int t;
scanf("%d", &t);
while (t--) {
ll n;
scanf("%lld", &n);
int mxc = 0;
ll mxv = 0;
for (ll i = 2; i * i <= n; i++) {
int cnt = 0;
while (n % i == 0) {
n /= i;
cnt++;
}
if (cnt > mxc) mxc = cnt, mxv = i;
}
printf("%d\n", max(mxc, 1));
if (mxc > 1) {
for (int i = 1; i <= mxc - 1; i++) printf("%lld ", mxv);
printf("%lld\n", (n / (ll)pow(mxv, mxc - 1)));
}
else printf("%lld\n", n);
}
return 0;
}