CF620

本文介绍了多项编程竞赛题目,包括Professor GukiZ的机器人、Dovlet祖父的计算器、一排珍珠、两个数组的问题以及区间异或和的解题思路和代码实现。涉及贪心算法、区间异或和的计算策略等编程技巧。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

A. Professor GukiZ’s Robot

思路

算出横着能走多少步, 竖着能走多少步。首先走到那个点肯定首先都要把这些步全部走完, 那么, 机器人每次可以同时走x, y各一步, 那么我们可以得出, 走完x, y后再走剩下的那些只向单方向走的步数, 总步数为 m a x ( x , y ) max(x, y) max(x,y)

代码

#include<bits/stdc++.h>

using namespace std;

int sx, sy;
int ex, ey;
int dx, dy;
int main()
{
	cin >> sx >> sy >> ex >> ey;
	 dx = abs(sx - ex);
	 dy = abs(sy - ey);
	//cout << dx << " " << dy << endl;
	int maxn = max(dx, dy);
	cout << maxn << endl; 
	return 0;
}

B. Grandfather Dovlet’s calculator

思路

首先求出每个数字又多少发光的杠, 然后从a遍历到b, 对于每个数x, 把他每一位拆出来并加即可。

代码

#include<bits/stdc++.h>

using namespace std;

long long num[10] = {6, 2, 5, 5, 4, 5, 6, 3, 7, 6};
int a, b;
long long cal(int x)
{
	long long res = 0;
	while(x)
	{
		int now = x % 10;
		x /= 10;
		res += num[now];
	}
	return res;
}
int main()
{
	cin >> a >> b;
	long long ans = 0;
	for(int i = a; i <= b; i++)
	{
		ans += cal(i);
	}
	cout << ans << endl;
	return 0;
}

C. Pearls in a Row

思路

贪心, 遇到两个一样的就分, 并标记。
如果最后一个不重复, 那把最后这些剩余的归到上一段中。
如果标记为0则输出-1

代码

#include<bits/stdc++.h>

using namespace std;

int n;
int a[300010];
int k;
set<int> s; 
int lp[300010];
int rp[300010];
bool flag = false;
int main()
{
	cin >> n;
	int l = 1; 
	for(int i = 1; i <= n; i++)
	{
		cin >> a[i];
		if(s.count(a[i]))
		{
			flag = true;
			k++;
			lp[k] = l;
			rp[k] = i;
			l = i+1;
			s.clear();
			continue;
		}
		s.insert(a[i]);
	}
	if(!flag)
	{
		printf("-1\n");
		return 0;
	}
	rp[k] = n;
	cout << k << endl;
	for(int i = 1; i  <= k; i++)
	{
		cout << lp[i] << " " << rp[i] << endl;
	}
	return 0;
}

D. Professor GukiZ and Two Arrays

这题wa没有A。

思路

我们可以把情况分为三种。

不用交换

直接算总和, 减掉即可

交换1个

O ( n 2 ) O(n^2) O(n2)枚举两数列交换的数;

交换两个

也是枚举两数列交换的数, 只不过其交换的数需要预处理。并排序

记录交换位置

WA代码

#include<bits/stdc++.h>

using namespace std;

int n, m;
int a[2010];
int b[2010];
long long ans1, ans2, ans3;	
long long sum1 = 0, sum2 = 0;
void cal1()
{
	ans1 = abs(sum2 - sum1);
 	return;
}
int sa, sb;
void cal2()
{
	ans2 = 1e18;
	for(int i = 1; i <= n; i++)
	{
		for(int j = 1; j <= m; j++)
		{
			long long suma = sum1;
			long long sumb = sum2;
			suma -= a[i];
			sumb -= b[j];
			suma += b[j];
			sumb += a[i];
			if(abs(suma - sumb) < ans2)
			{
				ans2 = abs(suma - sumb);
				sa = i;
				sb = j;
			}
		}
	}
}
map<long long, pair<int, int> > mpa;
map<long long, pair<int, int> > mpb; 
long long paira[2000010];
long long pairb[2000010];
int sa1, sa2, sb1, sb2;
void cal3()
{
	ans3 = 1e18;
	int cnta = 0, cntb = 0;
	
	for(int i = 1; i <= n; i++)
	{
		for(int j = i + 1; j <= n; j++)
		{
			long long now = a[i] + a[j];
			mpa[now] = make_pair(i, j);
			paira[++cnta] = now;
		}
	}
	for(int i = 1; i <= m; i++)
	{
		for(int j = i + 1; j <= m; j++)
		{
			long long now = b[i] + b[j];
			mpb[now] = make_pair(i, j);
			pairb[++cntb] = now;
		}
	}
	for(int i = 1; i <= cnta; i++)
	{
		for(int j = 1; j <= cntb; j++)
		{
			long long suma = sum1;
			long long sumb = sum2;
			suma = suma - paira[i] + pairb[j];
			sumb = sumb - pairb[j] + paira[i];
			if(abs(suma - sumb) < ans3)
			{
				ans3 = abs(suma - sumb);
				sa1 = mpa[paira[i]].first;
				sa2 = mpa[paira[i]].second;
				sb1 = mpb[pairb[i]].first;
				sb2 = mpb[pairb[i]].second;
			}
		}
	}
}
int main()
{
	cin >> n;
	for(int i = 1; i <= n; i++)
	{
		cin >> a[i];
	}
	cin >> m;
	for(int j = 1; j <= m; j++)
	{
		cin >> b[j];
	}
	for(int i = 1; i <= n; i++)
	{
		sum1 += a[i]; 
	}
	for(int j = 1; j <= m; j++)
	{
		sum2 += b[j];
	}
	cal1();
	cal2();
	cal3(); 
	if(ans1 <= ans2 && ans1 <= ans3)
	{
		cout << ans1 << endl;
		cout << 0 << endl;
	}
	else if(ans2 <= ans1 && ans2 <= ans3)
	{
		cout << ans2 << endl;
		cout << 1 << endl;
		cout << sa << " " << sb << endl;
	}
	else
	{
		cout << ans3 << endl;
		cout << 2 << endl;
		cout << sa1 << " " << sb1 << endl;
		cout << sa2 << " " << sb2 << endl;
	}
	return 0;
}

AC代码

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <cctype>
#include <algorithm>
#include <vector>
namespace OI
{
    #define pk putchar(' ')
    #define ph puts("")
    #define fi first
    #define se second
    template<class T>
    T Fabs(T x)
    {
        return x < 0 ? -x : x;
    }
    template<class T>
    void rd(T &x)
    {
        x = 0;
        int f = 1;
        char c;
        while (!isdigit(c = getchar())) if (c == '-') f = -1;
        do
        {
            x = (x << 3) + (x << 1) + (c ^ 48);
        } while (isdigit(c = getchar()));
        x *= f;
    }
    template<class T>
    void pt(T x)
    {
        if (x < 0)
            putchar('-'), x = -x;
        if (x > 9)
            pt(x / 10);
        putchar(x % 10 ^ 48);
    }
}
using namespace OI;
using namespace std;
typedef long long ll;
const int N = 2005;
int n, m, a[N], b[N], kind;
ll sa, sb;
vector<pair<int, pair<int, int> > > suma, sumb;
pair<int, int> ans[2];
int main()
{
    rd(n);
    for (int i = 1; i <= n; i++)
        rd(a[i]), sa += a[i];
    rd(m);
    for (int i = 1; i <= m; i++)
        rd(b[i]), sb += b[i];
    for (int i = 1; i < n; i++)
        for (int j = i + 1; j <= n; j++)
            suma.push_back({a[i] + a[j], {i, j}});
    for (int i = 1; i < m; i++)
        for (int j = i + 1; j <= m; j++)
            sumb.push_back({b[i] + b[j], {i, j}});
    sort(suma.begin(), suma.end());
    sort(sumb.begin(), sumb.end());
    ll minx = Fabs(sa - sb);
    for (int i = 1; i <= n; i++)
        for (int j = 1; j <= m; j++)
        {
            ll tmp = Fabs(sa - sb + 2ll * b[j] - 2ll * a[i]);
            if (tmp < minx)
            {
                minx = tmp;
                kind = 1;
                ans[0] = {i, j};
            }
        }
    for (int i = 0, j = 0; i < (int)suma.size() && j < (int)sumb.size();)
    {
        ll tmp = (sa - sb + 2ll * sumb[j].fi - 2ll * suma[i].fi);
        if (Fabs(tmp) < minx)
        {
            minx = Fabs(tmp);
            kind = 2;
            ans[0] = {suma[i].se.fi, sumb[j].se.fi};
            ans[1] = {suma[i].se.se, sumb[j].se.se};
        }
        if (tmp > 0)
            i++;
        else
            j++;
    }
    pt(minx), ph, pt(kind), ph;
    for (int i = 0; i < kind; i++)
        pt(ans[i].fi), pk, pt(ans[i].se), ph;
    return 0;
}

F. Xors on Segments

思路

前缀异或和;
区间异或和等于前缀异或和两端点异或: s u m l − 1 ⊕ s u m r = 区 间 异 或 和 [ l , r ] sum_{l-1} \oplus sum{r} = 区间异或和[l,r] suml1sumr=[l,r]
证明: s u m r = s u m l − 1 ⊕ [ l , r ] sum_r = sum_{l-1} \oplus [l,r] sumr=suml1[l,r]
s u m l − 1 ⊕ s u m r = s u m l − 1 ⊕ s u m l − 1 ⊕ [ l , r ] = [ l , r ] sum_{l-1} \oplus sum_r = sum_{l-1} \oplus sum_{l-1} \oplus[l,r] = [l,r] suml1sumr=suml1suml1[l,r]=[l,r]
所以得证;
我们可以枚举每一个左端点, 做n次DP。
每次DP固定了左端点i, 设f[j]表示以i为左端点, 右端点为j的最大异或和。
这样的话,对于每个询问, 只要它包含这个左端点, 也就是与这个左端点有交集,那么我们就更新他的答案, f[r]是以i为左端点在当前[l,r]区间询问的异或最大值

代码

#include<bits/stdc++.h>

using namespace std;

int n;
int m;
int a[50010];
int sum[1000010];
int l[5010];
int r[5010];
int f[50010];
int ans[5010];
int main()
{
	for(int i = 1; i <= 1000010; i++)
	{
		sum[i] = sum[i-1] ^ i;
	}
	
	cin >> n >> m;
	for(int i = 1; i <= n; i++)
	{
		cin >> a[i];
	}
	for(int i = 1; i <= m; i++)
	{
		cin >> l[i] >> r[i];
	}
	for(int i = 1; i <= n; i++)
	{
		f[i] = a[i];
		for(int j = i + 1; j <= n; j++)
		{
			f[j] = max(f[j-1], sum[min(a[i], a[j])-1] ^ sum[max(a[i], a[j])]);
		}
		for(int j = 1; j <= m; j++)
		{
			 if(i >= l[j] && i <= r[j])
			 {
			 	ans[j] = max(ans[j], f[r[j]]);
			 }
		}	
	}
	for(int i = 1; i <= m; i++)
	{
		cout << ans[i] << endl;
	}
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值