Codeforces 892C/D
C. Pride
传送门:http://codeforces.com/contest/892/problem/C
本题是一个关于序列的数学问题——最大公约数(GCD)。
对于一个长度为n的序列A={a[i]|i=1,2,...,n},有以下操作:选定序列中的两个相邻元素,记为x和y,将其中一个替换成gcd(x,y)。这个序列是否可以在有限步操作后,变成一个所有元素均为1的序列?若可行,则求最小操作步数;否则返回-1。
首先考虑可行性:若gcd{a[i]|i=1,2,...,n}=1,则可行;否则不可行。
之后,考虑每一个元素的情况:记cnt=card{i|a[i]=1},则当cnt>0时,ans=n-cnt。
之后,考虑每一段区间l~r(l<r)上的情况:记g(l,r)=gcd{a[i]|i=l,...,r},则有以下递推关系式:g(l,r+1)=gcd(g(l,r),a[r+1])。若存在l<r,使得g(l,r)=1,令d=r-l,则有操作步数step=n+d-1。
注意这个操作步数的计算。在当前情况下,首先在区间l~r上构造出一个元素1:d步;再用这个1与其他元素作GCD运算:n-1步。于是总操作步数为step=n+d-1。
于是,枚举l、r,求最小的d=r-l即可。时间复杂度为O(n2)。参考程序如下:
#include <stdio.h>
#include <stdlib.h>
#define MAX_N 2000
#define INF 0xffff int a[MAX_N]; int gcd(int x, int y)
{
if (y == ) return x;
return gcd(y, x % y);
} int main(void)
{
int n;
scanf("%d", &n);
int cnt = ;
for (int i = ; i < n; i++) {
scanf("%d", &a[i]);
if (a[i] == ) cnt++;
}
if (cnt) {
printf("%d\n", n - cnt);
exit();
}
int d = INF;
for (int i = ; i < n; i++) {
int g = a[i];
for (int j = i + ; j < n; j++) {
g = gcd(g, a[j]);
if (g == && j - i < d) d = j - i;
}
}
if (d != INF) printf("%d\n", n + d - );
else printf("-1\n");
return ;
}
D. Gluttony
传送门:http://codeforces.com/contest/892/problem/D
本题是一个关于序列的数学问题——重排问题。
给定由n个不同元素组成的序列A={a[i]|i=1,2,...,n},试将其重排为序列B={b[i]|i=1,2,...,n},使得对于任意一个{1,2,...,n}的非空真子集S,有$\sum_{i\in S}a[i] \neq\sum_{i\in S}b[i]$。
首先考虑一个特殊的情形:序列A是上升的。此时,只要将A循环左移一位,即得到满足条件的序列B。这个序列B的通项为b[i]=a[i%n+1],i=1,2,...,n。下证之:
由于序列B由序列A重排而来,因此$\sum_{i=1}^{n}a[i] =\sum_{i=1}^{n}b[i]$,记这个和为X。
对于i=1,2,...,n-1,有b[i]=a[i+1]>a[i];此外,有b[n]=a[1]<a[n]。
于是,①若n不是集合S中的元素,则显然有$\sum_{i\in S}a[i] <\sum_{i\in S}b[i]$;
②若n是集合S中的元素,则记集合T={1,2,...,n}-S,则n不是集合T中的元素,因此有$\sum_{i\in T}a[i] <\sum_{i\in T}b[i]$。于是,$\sum_{i\in S}a[i] =X-\sum_{i\in T}a[i] >X-\sum_{i\in T}b[i] =\sum_{i\in S}b[i]$。
综上所述,对于任意一个{1,2,...,n}的非空真子集S,有$\sum_{i\in S}a[i] \neq\sum_{i\in S}b[i]$。
循环移位操作是{1,2,...,n}上的一个变换,记为G:g(i)=i%n+1。
于是,对于一个有序的A,进行简单的循环移位操作。而对于一个无序的A,则考虑先排序。
设f(i)表示序列A中第i小的元素在A中的位置,即A中第i小的元素为a[f(i)]。于是,可将F:f(i)看作{1,2,...,n}上的一个变换。变换F可以通过排序构造,时间复杂度为O(nlogn)~O(n2)。
如此,设序列C={a[f(i)]|i=1,2,...,n},则C是一个上升序列,通项为c[i]=a[f(i)],i=1,2,...,n。于是,可以对C进行循环移位,生成序列D。则D的通项为d[i]=c[i%n+1]=a[f(i%n+1)]。
由于C=F(A),D=G(C),故所求序列B满足D=F(B)。由式D=F(B),有b[f(i)]=d[i]=a[f(i%n+1)]。
参考程序如下:
#include <stdio.h>
#define MAX_N 22 int a[MAX_N], b[MAX_N], f[MAX_N]; int main(void)
{
int n;
scanf("%d", &n);
for (int i = ; i < n; i++) {
scanf("%d", &a[i]);
f[i] = i;
}
for (int i = ; i < n; i++) {
for (int j = ; j < i; j++) {
if (a[f[i]] < a[f[j]]) {
int t = f[i];
f[i] = f[j];
f[j] = t;
}
}
}
for (int i = ; i < n; i++)
b[f[i]] = a[f[(i + ) % n]];
for (int i = ; i < n; i++)
printf("%d ", b[i]);
return ;
}
Codeforces 892C/D的更多相关文章
- codeforces #446 892A Greed 892B Wrath 892C Pride 891B Gluttony
A 链接:http://codeforces.com/problemset/problem/892/A 签到 #include <iostream> #include <algor ...
- python爬虫学习(5) —— 扒一下codeforces题面
上一次我们拿学校的URP做了个小小的demo.... 其实我们还可以把每个学生的证件照爬下来做成一个证件照校花校草评比 另外也可以写一个物理实验自动选课... 但是出于多种原因,,还是绕开这些敏感话题 ...
- 【Codeforces 738D】Sea Battle(贪心)
http://codeforces.com/contest/738/problem/D Galya is playing one-dimensional Sea Battle on a 1 × n g ...
- 【Codeforces 738C】Road to Cinema
http://codeforces.com/contest/738/problem/C Vasya is currently at a car rental service, and he wants ...
- 【Codeforces 738A】Interview with Oleg
http://codeforces.com/contest/738/problem/A Polycarp has interviewed Oleg and has written the interv ...
- CodeForces - 662A Gambling Nim
http://codeforces.com/problemset/problem/662/A 题目大意: 给定n(n <= 500000)张卡片,每张卡片的两个面都写有数字,每个面都有0.5的概 ...
- CodeForces - 274B Zero Tree
http://codeforces.com/problemset/problem/274/B 题目大意: 给定你一颗树,每个点上有权值. 现在你每次取出这颗树的一颗子树(即点集和边集均是原图的子集的连 ...
- CodeForces - 261B Maxim and Restaurant
http://codeforces.com/problemset/problem/261/B 题目大意:给定n个数a1-an(n<=50,ai<=50),随机打乱后,记Si=a1+a2+a ...
- CodeForces - 696B Puzzles
http://codeforces.com/problemset/problem/696/B 题目大意: 这是一颗有n个点的树,你从根开始游走,每当你第一次到达一个点时,把这个点的权记为(你已经到过不 ...
随机推荐
- 【Git使用具体解释】Egit使用过程中遇到的问题及解决的方法
1. Git错误non-fast-forward后的冲突解决 问题(Non-fast-forward)的出现原因在于:git仓库中已经有一部分代码,所以它不同意你直接把你的代码覆盖上去.于是你有2 ...
- Android学习笔记之:android更新ui的几种经常用法
Android主线程不能运行耗时操作.我们通常是在子线程中运行耗时操作, 我们在运行完耗时操作后,我们一般能够通过下面几种方式来实现ui界面的更新. 首先是布局文件: <LinearLayout ...
- hdu 1010 Tempter of the Bone (奇偶性剪枝)
题意:有一副二维地图'S'为起点,'D'为终点,'.'是可以行走的,'X'是不能行走的.问能否只走T步从S走到D? 题解:最容易想到的就是DFS暴力搜索,,但是会超时...=_=... 所以,,要有其 ...
- Codeforces Round #332 (Div. 2) B. Spongebob and Joke 模拟
B. Spongebob and Joke While Patrick was gone shopping, Spongebob decided to play a little trick ...
- android按钮被点击文字颜色变化效果
有的时候做应用需要点击按钮时文字颜色也跟着变,松开后又还原,目前发现两种解决方案:第一用图片,如果出现的地方比较多,那么图片的量就相当可观:第二,也就是本文讲到的.废话少说,先贴图片,再上代码. 正常 ...
- Git 少用 Pull 多用 Fetch 和 Merge 【已翻译100%】【转】
本文转载自:https://www.oschina.net/translate/git-fetch-and-merge?lang=chs&page=1# 本文有点长而且有点乱,但就像Mark ...
- GROUPPING和ROLLUP的基本知识
1.GROUPPING 是一个聚合函数,它产生一个附加的列,当用 CUBE 或 ROLLUP 运算符添加行时,附加的列输出值为1,当所添加的行不是由 CUBE 或 ROLLUP 产生时,附加列值为0. ...
- MSSQL:查看作业情况
select j.name 'Job名', j.description '描述', j.ENABLED job_enabled, cast(js.last_r ...
- linux ssh文件输
在linux下一般用scp这个命令来通过ssh传输文件. 1.从服务器上下载文件scp username@servername:/path/filename /var/www/local_dir(本地 ...
- BZOJ 4565 状压DP
思路: f[i][j][S]表示从i到j压成S状态 j-m是k-1的倍数 $f[i][j][S<<1]=max(f[i][j][S<<1],f[i][m-1][S]+f[m][ ...