Codeforces Round #713 (Div. 3) 题解

本场链接:Codeforces Round #713 (Div. 3)

A. Spy Detected!

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define forn(i,x,n) for(int i = x;i <= n;++i)
#define forr(i,x,n) for(int i = n;i >= x;--i)
#define Angel_Dust ios::sync_with_stdio(0);cin.tie(0)
typedef pair<int,int> pii;
#define x first
#define y second

const int N = 105;
int a[N];

int main()
{
	int T;scanf("%d",&T);
	while(T--)
	{
		int n;scanf("%d",&n);
		map<int,int> st;
		forn(i,1,n)
		{
			scanf("%d",&a[i]);
			++st[a[i]];
		}
		forn(i,1,n)
		{
			if(st[a[i]] == 1)	
			{
				printf("%d\n",i);
				break;
			}
		}
	}
    return 0;
}

B. Almost Rectangle

注意越界情况

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define forn(i,x,n) for(int i = x;i <= n;++i)
#define forr(i,x,n) for(int i = n;i >= x;--i)
#define Angel_Dust ios::sync_with_stdio(0);cin.tie(0)
typedef pair<int,int> pii;
#define x first
#define y second

const int N = 405;
char s[N][N];

int main()
{
	int T;scanf("%d",&T);
	while(T--)
	{
		int n;scanf("%d",&n);
		forn(i,1,n)	scanf("%s",s[i] + 1);
		
		int x1 = -1,y1,x2,y2;
		forn(i,1,n)	forn(j,1,n)
		{
			if(s[i][j] == '.')	continue;
			if(x1 == -1)	x1 = i,y1 = j;
			else	x2 = i,y2 = j;
		}
		
		if(x1 == x2)
		{
			if(x1 + 1 <= n)	s[x1 + 1][y1] = s[x2 + 1][y2] = '*';
			else	s[x1 - 1][y1] = s[x2 - 1][y2] = '*';
		}
		else if(y1 == y2)
		{
			if(y1 + 1 <= n)	s[x1][y1 + 1] = s[x2][y2 + 1] = '*';
			else	s[x1][y1 - 1] = s[x2][y2 - 1] = '*';
		}
		else	s[x2][y1] = s[x1][y2] = '*';
		
		forn(i,1,n)	printf("%s\n",s[i] + 1);
	}
    return 0;
}

C. A-B Palindrome

特别的:在第一轮循环的时候仅限于处于一边是问号一边不是的,因为做到一半可能需要的1会比0更多,但是从整体上来看填0会更好。放到后面处理,混在一起无法判断。

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define forn(i,x,n) for(int i = x;i <= n;++i)
#define forr(i,x,n) for(int i = n;i >= x;--i)
#define Angel_Dust ios::sync_with_stdio(0);cin.tie(0)
typedef pair<int,int> pii;
#define x first
#define y second

const int N = 2e5+7;
char s[N];

int main()
{
	int T;scanf("%d",&T);
	while(T--)
	{
		int a,b;scanf("%d%d",&a,&b);
		int n = a + b,need0 = 0,need1 = 0;
		scanf("%s",s + 1);
		forn(i,1,n)	if(s[i] == '0')	++need0;else if(s[i] == '1')	++need1;
		need0 = a - need0,need1 = b - need1;
		if(need0 < 0 || need1 < 0)
		{
			puts("-1");
			continue;
		}

		bool ok = 1;
		forn(l,1,n / 2)
		{
			int r = n - l + 1;
			if(s[l] == s[r])
			{
				continue;
			}
			else
			{
				if(s[l] != '?')	swap(s[l],s[r]);
				if(s[l] != '?')	
				{
					ok = 0;
					break;
				}
				if(s[r] == '0')
				{
					if(!need0)	
					{
						ok = 0;
						break;
					}
					--need0;
					s[l] = '0';
				}
				else
				{
					if(!need1)
					{
						ok = 0;
						break;
					}
					--need1;
					s[l] = '1';
				}
			}
		}
		
		forn(l,1,n / 2)
		{
			int r = n - l + 1;
			if(s[l] == s[r] && s[l] == '?')
			{
				if(need1 >= need0)
				{
					if(need1 < 2)	
					{
						ok = 0;
						break;
					}
					need1 -= 2;
					s[l] = '1';s[r] = '1';
				}		
				else
				{
					if(need0 < 2)
					{
						ok = 0;
						break;
					}
					need0 -= 2;
					s[l] = '0';s[r] = '0';
				}
			}
		}
		
		if(n % 2)
		{
			if(s[(n + 1) / 2] == '?')
			{
				if(!need1 && !need0)
				{
					ok = 0;
					break;
				}
				else if(need1)
				{
					--need1;
					s[(n + 1) / 2] = '1';
				}
				else
				{
					--need0;
					s[(n + 1) / 2] = '0';
				}
			}
		}
		
		if(need1 || need0)	ok = 0;
		
		if(!ok)	puts("-1");
		else printf("%s\n",s + 1);
	}
    return 0;
}

D. Corrupted Array

特判:\(x = b[n + 1]\)的情形。

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define forn(i,x,n) for(int i = x;i <= n;++i)
#define forr(i,x,n) for(int i = n;i >= x;--i)
#define Angel_Dust ios::sync_with_stdio(0);cin.tie(0)

const int N = 2e5+7;
ll b[N];

int main()
{
	int T;scanf("%d",&T);
	while(T--)
	{
		int n;scanf("%d",&n);
		ll sum = 0;
		map<ll,int> st;
		forn(i,1,n + 2)	scanf("%lld",&b[i]),sum += b[i],++st[b[i]];
		
		bool ok = 0;
		ll x = -1;
		forn(i,1,n + 2)
		{
			if((sum - b[i]) % 2)	continue;
			--st[b[i]];
			if(st.count((sum - b[i]) / 2) && st[(sum - b[i]) / 2])
			{
				ok = 1;
				x = b[i];
				break;
			}
			++st[b[i]];
		}
		if(!ok)	puts("-1");
		else
		{
			bool xflag = 0,sflag = 0;
			forn(i,1,n + 2)
			{
				if(b[i] == x && !xflag)
				{
					xflag = 1;
					continue;
				}
				else if(b[i] == (sum - x) / 2 && !sflag)
				{
					sflag = 1;
					continue;
				}
				printf("%lld ",b[i]);
			}
			puts("");
		}
	}
    return 0;
}

E. Permutation by Sum

容易想到一个结论:求出一段区间能构造出来的最小答案和最大答案,在这之间的答案都可以构造出来。

对于\(n\)个数填进\(k\)个位置的情况:最小的总和是\((k + 1) * k / 2\),最大的情况对称。

倒着枚举每个数,只要能塞进去就塞。

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define forn(i,x,n) for(int i = x;i <= n;++i)
#define forr(i,x,n) for(int i = n;i >= x;--i)
#define Angel_Dust ios::sync_with_stdio(0);cin.tie(0)
typedef pair<int,int> pii;
#define x first
#define y second

const int N = 505;
int ans[N];

int main()
{
	int T;scanf("%d",&T);
	while(T--)
	{
		int n,l,r,s;scanf("%d%d%d%d",&n,&l,&r,&s);
		forn(i,1,n)	ans[i] = 0;
		
		int k = r - l + 1;
		forr(i,1,n)
		{
			if(k > 0 && k * (2 * i + 1 - k) / 2 >= s && s - i >= k * (k - 1) / 2)
			{
				ans[l + k - 1] = i;
				--k;
				s -= i;
			}
		}
		
		if(k)
		{
			puts("-1");
			continue;
		}
		
		set<int> st;forn(i,l,r)	st.insert(ans[i]);
		int ga = 1;while(st.count(ga))	ga++;
		forn(i,1,n)
		{
			if(ans[i])	continue;
			ans[i] = ga;
			st.insert(ga);
			while(st.count(ga))	++ga;
		}
		forn(i,1,n)	printf("%d ",ans[i]);
		puts("");
	}
    return 0;
}

F. Education

显然枚举答案:考虑最终停留在的位置。维护当前手上的钱以及为了走到这个位置已经度过了多少天数。更新答案即可。

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define forn(i,x,n) for(int i = x;i <= n;++i)
#define forr(i,x,n) for(int i = n;i >= x;--i)
#define Angel_Dust ios::sync_with_stdio(0);cin.tie(0)
typedef pair<int,int> pii;
#define x first
#define y second

const int N = 2e5+7;
ll a[N],b[N];

int main()
{
	int T;scanf("%d",&T);
	while(T--)
	{
		ll n,c;scanf("%lld%lld",&n,&c);
		forn(i,1,n)	scanf("%lld",&a[i]);
		forn(i,1,n - 1)	scanf("%lld",&b[i]);
		ll have = 0,res = 1e18,cur = 0;
		forn(i,1,n)
		{
			res = min(res,(c - have + a[i] - 1) / a[i] + cur);
			ll need = (b[i] - have + a[i] - 1) / a[i];
			have += a[i] * need - b[i];cur += need + 1;
		}	
		printf("%lld\n",res);
	}
    return 0;
}

G. Short Task

显然线性筛,考虑线性筛怎么求因数和:

  • 对于\(p\in primes\),显然有\(d[p] = p + 1\).

  • 对于\(i\),若\(i\%primes[j] == 0\)说明\(primes[j]\)不是\(i\)的最小因子,把因数和公式展开后可以得到结论:\(d[i * primes[j]] = d[i] * (primes[j] + 1)\)

  • 若\(i\%pirmes[j] != 0\)说明\(primes[j]\)是\(i\)的最小因子,考虑维护每个数对应的最小质因子的在约数和中的贡献:即\(1+p+p^2+...p^{w_1}\),其中\(p\)是\(i\)的最小质因子。则\(d[i * primes[j]] = d[i] / minp[i] * minp[i * primes[j]]\).

  • 维护\(minp\)部分:质数显然,若\(primes[j]\)不是\(i\)的最小质因子,那么\(minp[i * primes[j]] = primes[j] + 1\).否则\(minp[i * primes[j]] = minp[i] * primes[j] + 1\).

最后将还在范围内的答案计入即可。由于\(n \leq d(n) \leq 1e7\)所以筛到1e7即可。

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define forn(i,x,n) for(int i = x;i <= n;++i)
#define forr(i,x,n) for(int i = n;i >= x;--i)
#define Angel_Dust ios::sync_with_stdio(0);cin.tie(0)
typedef pair<int,int> pii;
#define x first
#define y second

const int N = 1e7+7;
int primes[N],cnt,ans[N];
ll minp[N],dsum[N];
bool st[N];

void init()
{
	dsum[1] = 1;
	for(int i = 2;i < N;++i)
	{
		if(!st[i])	primes[cnt++] = i,dsum[i] = i + 1,minp[i] = i + 1;
		for(int j = 0;j < cnt && 1ll*primes[j] * i < N;++j)
		{
			st[primes[j] * i] = 1;
			if(i % primes[j])	dsum[i * primes[j]] = dsum[i] * (primes[j] + 1),minp[i * primes[j]] = primes[j] + 1;
			else
			{
				minp[i * primes[j]] = minp[i] * primes[j] + 1;
				assert(minp[i] != 0);
				dsum[i * primes[j]] = dsum[i] / minp[i] * minp[i * primes[j]];
				break;
			}
		}
	}
	forn(i,1,N - 1)	if(dsum[i] < N && !ans[dsum[i]])	ans[dsum[i]] = i;
}

int main()
{
	init();
	
	int T;scanf("%d",&T);
	while(T--)
	{
		int n;scanf("%d",&n);
		printf("%d\n",ans[n] == 0 ? -1 : ans[n]);
	}
    return 0;
}
上一篇:E - Permutation by Sum Codeforces Round #713 (Div. 3)


下一篇:【LeetCode-713】乘积小于K的子数组