Codeforces Round #671Div. 2
D1/2(Sage’s Birthday)
题意:给定序列 a n a_n an,要求重新排序,让谷最多,即( a i − 1 < a i < a i + 1 a_{i-1}<a_i<a_{i+1} ai−1<ai<ai+1)。输出序列并且给出最多的个数。
D 1 和 2 的 区 别 是 e a s y 版 本 里 面 的 数 字 大 小 不 一 样 , h a r d 可 能 相 同 D1和2的区别是easy版本里面的数字大小不一样,hard可能相同 D1和2的区别是easy版本里面的数字大小不一样,hard可能相同
思路:
不一样的时候能够想到是分奇数和偶数位置,sort以后在偶数位置从 a 1 a_1 a1开始递增放入序列,奇数位置也是按着递增把剩下的放入。
一样的化手推发现可能就是有几个原来的位置不作数了,我就来了两遍,第一个是上面的做法,记录谷的个数从solve返回;第二种把原来的奇数位置反向放(递减),再来一遍记录答案 o u t out out。比较大小输出
正确性婷婷也不知道^^
int n, a[maxn], ans[maxn], ans1[maxn];
int solve() {
int nw = 0, co = 0;
for (int i = 2; i <= n; i += 2) {
ans1[i] = a[++nw];
}
for (int i = 1; i <= n; i += 2) {
ans1[i] = a[++nw];
}
for (int i = 2; i <= n; i += 2) {
if (ans1[i] < ans1[i + 1] && ans1[i] < ans1[i - 1])co++;
}
return co;
}
int main() {
int head = 0;
cin >> n;
int w = n + 1, out = 0;
for (int i = 1; i <= n; i++)cin >> a[i];
sort(a + 1, a + 1 + n);
for (int i = 1; i <= n; i+=2) {
ans[i] = a[--w];
}
for (int i = 2; i <= n; i += 2) {
ans[i] = a[++head];
if (ans[i] < ans[i + 1] && ans[i] < ans[i - 1])out++;
}
int a1 = solve();
if (out > a1) {
cout << out << endl;
for (int i = 1; i <= n; i++) {
cout << ans[i] << " ";
}
cout << endl;
}
else {
cout << a1 << endl;
for (int i = 1; i <= n; i++) {
cout << ans1[i] << " ";
}
cout << endl;
}
return 0;
}
E. Decryption(因数分解、构造)
link
题意:给定合数 n n n,把他们的因子分出来,自己排顺序放在一个环上。要求相邻的数字 g c d ≠ 1 gcd\ne1 gcd=1。可以进行另外的向两数插入 l c m lcm lcm的操作。要求输出最小的操作数的序列
思路:都已经开始合数了必然开素数或者因数分解。但是 n ≤ 1 0 9 n\le10^9 n≤109,应该不能线性筛上了。
- 考虑用 n \sqrt{n} n筛出他的因子(不包括素数) f a c i fac_i faci,找出因子的同时判断是不是素数( f a c i \sqrt{fac_i} faci判断),是的化存到 p i p_i pi.我对他们进行了去重,考虑到之后可能有素数的次数 ≠ 1 \ne1 =1
- 操作数最小只可能有两种情况: ( a ) (a) (a)合数由两个次数为1的素数组成,操作数1 ( b ) (b) (b)其他,操作数为0
- 构造:数轴上放去重之后的素数组 p n p_n pn,在两个 p i 与 p i + 1 ( i < s u m p ( 素 数 总 个 数 ) ) p_i与p_{i+1}(i<sump(素数总个数)) pi与pi+1(i<sump(素数总个数))之间先放上 f a c n fac_n facn中不等于 去 素 数 因 子 组 p i ∗ p i + 1 去素数因子组p_i*p_{i+1} 去素数因子组pi∗pi+1的 包 含 p i 包含p_i 包含pi的合数,然后放上 p i ∗ p i + 1 p_i*p_{i+1} pi∗pi+1。在 p s u m p p_{sump} psump与n之间把余下的放上,记得去重
int n;
int p[maxn], fac[maxn];
map<int, int>vis, facp, pp;
int main() {
int T;
int sumfac, sump, minn, flag, anss, tt;
cin >> T;
//primes((int)(sqrt(1e9)));
while (T--)
{
cin >> n;
vis.clear();
facp.clear();
pp.clear();
sumfac = 0; sump = 0;
for (int i = 2; (LL)i*i <= (LL)n; i++) {
if (n%i == 0) {
/*fac[++sumfac] = i;
if (n / i != i)fac[++sumfac] = n / i;*/
flag = 0;
minn = i;
for (int j = 2; (LL)j*j <= (LL)minn; j++) {
if (minn%j == 0) {
flag = 1;
break;
}
}
if (!flag) {
if(pp[minn]==0)p[++sump] = minn; pp[minn]++; }
else {
if (facp[minn] == 0)fac[++sumfac] = minn; facp[minn] = 1; }
flag = 0;
minn = n / i;
for (int j = 2; (LL)j*j <= (LL)minn; j++) {
if (minn%j == 0) {
flag = 1;
break;
}
}
if (!flag) {
if (pp[minn] == 0)p[++sump] = minn; pp[minn]++; }
else {
if (facp[minn] == 0)fac[++sumfac] = minn; facp[minn] = 1; }
}
}
if (sump == 2 && sumfac == 0) {
cout << p[1] << " " << p[2] << " " << n << endl;
cout << 1 << endl;
continue;
}
for (int i = 1; i < sump; i++) {
if (vis[p[i]])continue;
cout << p[i] << " ";
vis[p[i]] = 1;
//ans[++anss] = p[i];
for (int j = 1; j <= sumfac; j++) {
if (fac[j] % p[i] == 0 && fac[j] != p[i] * p[i + 1] && vis[fac[j]] == 0) {
cout << fac[j] << " "; vis[fac[j]] = 1; }
}
if (vis[p[i] * p[i + 1]] == 0) {
cout << p[i] * p[i + 1] << " "; vis[p[i] * p[i + 1]] = 1; }
//ans[++anss] = p[i] * p[i + 1];
}
cout << p[sump] << " ";
for (int i = 1; i <= sumfac; i++) {
if (fac[i] % p[sump] == 0 && vis[fac[i]] == 0) {
cout << fac[i] << " "; vis[fac[i]] = 1; }
}
cout << n << endl;
cout << 0 << endl;
//ans[++anss] = n;
}
return 0;
}