2021“MINIEYE杯”中国大学生算法设计超级联赛(6)
1001.Yes, Prime Minister
- 题意
给出一个数x ((-10^7 <= x _i <= 10^7)) 让你求出最小的一对(l,r)且((l <= x_i <= r)) 中 ((sum_{i=l}^r i)) 为质数。
- 思路
推了一会就开始打表了,打了个表规律就非常的清晰了。
- 一个正数x,要么自己的质数,要么(2 * x + 1) | (2 * x - 1)是质数,要么就直接从-x到x,之后在一直找大于x的同性质成立的质数就行了,两个质数之间距离 / 2相差应该不大,之间暴力找就行了
- 负数-x,直接先加到x变成0,之后往后面找一个为质数或两个相加为质数的情况即可
code :
void solve()
{
int n;
cin >> n;
int ans = 0;
if (n <= 0)
{
if (n == 0)
cout << "3" << endl;
else
{
int x = abs(n) + 1;
int res = 0;
for (int i = 0; i <= 60; i++)
{
int y = x + i;
if (!st[y])
{
cout << 2 * y << endl;
return;
}
if (!st[2 * y + 1])
{
cout << 2 * y + 1 << endl;
return;
}
}
}
}
else
{
if (!st[n])
cout << "1" << endl;
else
{
int res = 0;
int x = n;
if (!st[2 * x - 1] || !st[2 * x + 1])
{
cout << "2" << endl;
return;
}
for (int i = 1; i <= 60; i++)
{
int y = x + i;
if (!st[y])
{
cout << 2 * y << endl;
return;
}
if (!st[2 * y + 1])
{
res = (2 * y + 1);
cout << res << endl;
return;
}
}
}
}
}
1004.Decomposition
- 题意
给你n个点形成的完全图,让你去将他分成k个简单图,每个简单图中,你需要有(l_i)条路径,而且,每个简单图中的顶点都是两两不同的。
- 思路
看懂题意后,其实就是一道构造题。
然后,你通过不断构造可以发现用欧拉回路去构造是完美的,然后你可以去欧拉回路中以每个点为起点进行增加边,题目说了最多(sumlimits_{i=1}^k l_i = frac{n(n-1)}{2})条边,那么只需要 (frac{n}{2} * n)个点放进去就够了,直接输出存起来的边即可。
code:
vector<int> ege;
int ST;
void solve(){
cout << "Case #" << ++ST << ":" << endl;
ege.clear();
int n,k;
cin >> n >> k;
ege.pb(n - 1);
for(int i = 0;i <= n / 2;i ++) {
int sgn = 1, now = i;
for(int j = 1;j < n;j ++) {
ege.pb(now);
// 欧拉回路中交替构造边
now = (now + sgn * j + n - 1) % (n - 1);
sgn *= -1;
}
ege.pb(n - 1);
}
int now = 0;
while(k --) {
int len;
cin >> len;
len ++;
while(len --) cout << ege[now ++] + 1 << (len?' ':'
');
now --;
}
}
1005.Median
- 题意
给出n,m, 并给出m个(b_i), 需要构造一个数组c,并且分割m个区间后,每个区间的中位数都是(b_i), 且数组C是由1,2 ··· n构成的,且唯一,你需要判断能否构造出这样的数组C
- 思路
直接找不为中位数的点,且把每段连续的点都存在不同的vector里,然后判断最长的段的大小和其他的大小进行相比。
- 如果这个最长的段小于其他的段,直接那么就一定存在解,输出yes即可
- 否则,最后剩下max(块) - sum(其他),然后遍历一遍中位数,记录小于这个块的最小值的中位数的数量cnt,然后比较 cnt 和 上面的剩下的即可。
code :
vector<vector<int> > v;
int a[N];
int st[N];
int cnt;
void solve(){
int n,m;
cin >> n >> m;
v.resize(m + 2);
for(int i = 1;i <= cnt;i ++) v[i].clear();
cnt = 1;
for(int i = 1;i <= n;i ++) st[i] = 0;
for(int i = 1;i <= m;i ++) {
cin >> a[i];
st[a[i]] = 1;
}
for(int i = 1;i <= n;i ++) {
if(!st[i]) {
v[cnt].push_back(i);
}else if(v[cnt].size()){
cnt ++;
}
}
int maxn = 0;
int sum = 0;
int id = 0;
for(int i = 1;i <= cnt;i ++) {
int k = v[i].size();
if(maxn < k) {
id = i;
maxn = k;
}
sum += k;
}
sum -= maxn;
if(n == m) {
cout << "YES" << endl;
return;
}
if(maxn < sum) {
cout << "YES" << endl;
return;
}
maxn -= sum;
int res = 0;
for(int i = 1;i <= m;i ++) {
if(a[i] < v[id][0]) res ++;
}
if(res >= maxn) {
cout << "YES" << endl;
}else {
cout << "NO" << endl;
}
}