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;
}
标签:cnt,int,题解,scanf,mxc,vector,Div,686,mx 来源: https://www.cnblogs.com/Saudi/p/14056876.html