Codeforces Round #696 (Div. 2) 1/19

比赛链接

T1

中文题意:
T组输入,每次输入一个字符串A,现在需要你找到一个字符串B,使得A+B(二进制加法)之后值最大。并且还有一个特殊的点在于,如果结果中存在连续的字符那么连续的字符会被浓缩成一个字符。
类似于A=111,B=111,得到结果会是A+B=222=2。现在要你输出字典序最大的结果是由哪个B得来的。 ∣ A ∣ ≤ 1 0 5 |A|\leq10^5 A105

一个思路,高位能加1就加1,高位加了1之后要么是1要么是2,根据高位调整低位即可。

const int N = 1e6 + 7;
 
ll n, m;
char s[N];
 
void solve() {
	n = read();
	scanf("%s", s + 1);
	rep(i, 1, n) {
		char tmp = s[i];
		tmp += 1;
		if (tmp != s[i - 1])	printf("1");
		else tmp -= 1, printf("0");
		s[i] = tmp;
	}
	puts("");
}

T2

中文题意:
T组输入,每组输入一个d,需要你找到一个符合要求的整数k。整数k一定要有4个及以上因子,并且每两个因子之间差值的绝对值大于等于d。
T ≤ 3000 , d ≤ 1 0 4 T\leq3000,d\leq10^4 T3000,d104

题目要求任意两个因子之间都要相差,那么我们构造的时候就不需要构造合数了,合数还能拆分维护比较麻烦。那么我们想找到这样的整数k,首先1一定是k的因子,那么我们找到一个大于等于d+1的质数不就行了吗,对着这个找到的质数再找到第二个比他大d的质数,这样两个质数的乘积构造出来的答案k,一定可以拆成四个因子,分别是1, p r i m e 1 prime_1 prime1 p r i m e 2 prime_2 prime2 p r i m e 1 ∗ p r i m e 2 prime_1*prime_2 prime1prime2。并且最小的质数都是2,跳跃间隔找到的答案,相乘之后一定会比前一个大d。符合要求。

const int N = 1e6 + 7;
 
ll n, m;
ll a[N];
 
bool vis[N];
int prime[N], cnt;
void getprime() {
	ms(vis, 1); vis[1] = 0;
	rep(i, 2, N - 1) {
		if (vis[i])	prime[++cnt] = i;
		rep(j, 1, cnt) {
			if (i * prime[j] >= N)	break;
			vis[i * prime[j]] = 0;
			if (i % prime[j] == 0)	break;
		}
	}
}
 
void solve() {
	n = read();
	m = *lower_bound(prime + 1, prime + 1 + cnt, n + 1);
	ll ans = m;
	m = *lower_bound(prime + 1, prime + 1 + cnt, m + n);
	ans *= m;
	print(ans);
}
 
int main() {
	getprime();
	int T = read();	while (T--)
		solve();
	return 0;
}

T3

中文题意:
T组输入,每组输入给出一组序列,你每次可以选择一个X,然后从这些序列中选取两个和为X的值删掉,并且下一次只能从删掉的两个值中选取更大的那个成为新的X重新进行上述操作,问这个序列能不能变为空的,并且如果可以变成空的,你第一步选取的X是多少,任意一个即可。
n ≤ 1 0 3 , a i ≤ 1 0 6 n\leq10^3,a_i\leq10^6 n103,ai106

观察可以发现,我们每次都要选择一个数是另外两个数的和,那么第一次选取的时候一定要选择到最大的哪一个元素,不然后面永远都无法把他删掉。那么固定一个之后,再去枚举剩余的点。使用集合模拟即可通过。注意如果即将要删掉的两个元素相等的时候怎么判断,小心一点。

const int N = 1e6 + 7;

int n, m;
int a[N];

vector<int> calc(int x) {
	multiset<int> st;
	rep(i, 1, n * 2)	st.insert(a[i]);
	vector<int> res;
	rep(i, 1, n) {
		auto it1 = --st.end();
		int y = *it1;
		st.erase(it1);
		auto it2 = st.find(x - y);
		if (it2 == st.end())	return {};
		res.push_back(y);
		res.push_back(x - y);
		x = max(y, x - y);
		st.erase(it2);
	}
	return res;
}

void solve() {
	n = read();
	rep(i, 1, n * 2)	a[i] = read();
	sort(a + 1, a + 1 + n * 2);
	rep(i, 1, n * 2 - 1) {
		int x = a[i] + a[2 * n];
		vector<int> res = calc(x);
		if (res.size()) {
			puts("YES");
			print(x);
			rep(j, 0, n - 1)
				printf("%d %d\n", res[2 * j], res[2 * j + 1]);
			return;
		}
	}
	puts("NO");
}

T4

中文题意:
T组输入,给出长度为n的数组,每次你可以把相邻位置一起减1。现在你有一次使用超能力的机会,交换两个相邻位置,也就是 s w a p ( a i , a i + 1 ) swap(a_i,a_{i+1}) swap(ai,ai+1),当然你也可以不使用超能力。在这样的前提下,问你是否可以把全部位置减为0。
n ≤ 2 ∗ 1 0 5 , a i ≤ 1 0 9 n\leq2*10^5,a_i\leq10^9 n2105,ai109

前后缀差分。首先我们如果不使用能力的话,直接从前到后差分一次,再从后往前差分一次,判断是不是有最终差分值等于0的时候。如果有说明不使用超能力也可以全部变成0。我们假设前缀差分数组为 p r e [ i ] pre[i] pre[i],后缀差分数组为 s u f [ i ] suf[i] suf[i]。那么交换两个相邻位置显然对 [ 1 , i − 1 ] [1,i-1] [1,i1]以及 [ i + 2 , n ] [i+2,n] [i+2,n]的区间答案是没有影响的。那么如果枚举到某个位置,它的前缀差分等于后一个位置的后缀差分,说明以这个位置作为终点不使用即可完成清零操作。如果要使用超能力呢,那么首先要保证交换后可以继续往后走。也就是 a i + 1 ≥ p r e i − 1 & & a i ≥ s u f i + 2 a_{i+1}\geq pre_{i-1} \&\&a_i\geq suf_{i+2} ai+1prei1&&aisufi+2。才可以把 i , i + 1 i,i+1 i,i+1两个位置清零,如果这样的前提下,可以使得前缀差分等于后缀差分,说明找到了解法,输出即可。

const int N = 1e6 + 7;
 
ll n, m;
ll a[N], pre[N], suf[N];
 
void solve() {
	n = read();
	pre[0] = suf[n + 1] = 0;
	rep(i, 1, n)	a[i] = read();
	rep(i, 1, n) {
		if (a[i] >= pre[i - 1])	pre[i] = a[i] - pre[i - 1];
		else pre[i] = INF;
	}
	for (int i = n; i; --i) {
		if (a[i] >= suf[i + 1])	suf[i] = a[i] - suf[i + 1];
		else suf[i] = INF;
	}
	if (!pre[n] or !suf[1]) { puts("YES");	return; }
	rep(i, 1, n - 1) {
		if (pre[i] != INF and pre[i] == suf[i + 1]) {
			puts("YES");
			return;
		}
		if (a[i] >= suf[i + 2] and a[i + 1] >= pre[i - 1]
			and a[i + 1] - pre[i - 1] == a[i] - suf[i + 2]) {
			puts("YES");
			return;
		}
	}
	puts("NO");
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值