首页 > 其他分享 >AtCoder Beginner Contest 199 (Sponsored by Panasonic) A~E 题解

AtCoder Beginner Contest 199 (Sponsored by Panasonic) A~E 题解

时间:2024-09-08 21:03:33浏览次数:2  
标签:AtCoder le 199 输出 int 题解 样例 输入 mathrm

A - Square Inequality

题目大意

给定三个整数\(A,B,C\)。判断\(A^2+B^2<C^2\)是否成立。

\(0\le A,B,C\le 1000\)

输入格式

\(A~B~C\)

输出格式

如果\(A^2+B^2<C^2\),输出Yes;否则,输出No

样例

\(A\) \(B\) \(C\) 输出
\(2\) \(2\) \(4\) Yes
\(10\) \(10\) \(10\) No
\(3\) \(4\) \(5\) No

分析

直接按题意计算即可。

代码

#include <cstdio>
using namespace std;

int main()
{
	int a, b, c;
	scanf("%d%d%d", &a, &b, &c);
	puts(a * a + b * b < c * c? "Yes": "No");
	return 0;
}

B - Intersection

题目大意

给定两个长度为\(N\)的序列:\(A = (A_1, A_2, A_3, \dots, A_N)\)和\(B = (B_1, B_2, B_3, \dots, B_N)\)。
找到符合如下条件的整数\(x\)的个数:

  • 对于所有的\(1\le i\le N\),\(A_i\le x\le B_i\)。

\(1\le N\le 100\)
\(1\le A_i\le B_i\le 1000\)

输入格式

\(N\)
\(A_1~A_2~\dots~A_N\)
\(B_1~B_2~\dots~B_N\)

输出格式

输出答案。

样例

样例输入1

2
3 2
7 5

样例输出1

3

\(x\)可以取\(3,4,5\)。

样例输入2

3
1 5 3
10 7 3

样例输出2

0

没有\(x\)符合条件。

样例输入3

3
3 2 5
6 9 8

样例输出3

2

分析

我们将\(x\)的限制条件拆解为:

  • 对于所有的\(1\le i\le N\),\(A_i\le x\)。
  • 对于所有的\(1\le i\le N\),\(x\le B_i\)。

这时,我们可以进一步简化条件:

  • \((\max A)\le x\)。
  • \(x\le (\min B)\)。

从而得到\((\max A)\le x\le (\min B)\),所以合法的\(x\)的个数为\(\max(0,\min B-\max A+1)\)。

代码

#include <cstdio>
using namespace std;

int main()
{
	int n, maxa = 1, minb = 1000;
	scanf("%d", &n);
	for(int i=0; i<n; i++)
	{
		int a;
		scanf("%d", &a);
		if(a > maxa) maxa = a;
	}
	while(n--)
	{
		int b;
		scanf("%d", &b);
		if(b < minb) minb = b;
	}
	if(maxa > minb) puts("0");
	else printf("%d\n", minb - maxa + 1);
	return 0;
}

C - IPFL

题目大意

给定长度为\(2N\)且只由大写英文字母组成的字符串\(S\)。
你要处理\(Q\)个请求。
第\(i\)个请求中由三个整数\(T_i,A_i\)和\(B_i\)组成:

  • 如果\(T_i=1\):交换\(S\)中第\(A_i\)和\(B_i\)个字符;
  • 如果\(T_i=2\),交换\(S\)中的前\(N\)个和后\(N\)个字符(如:FLIP\(\to\)IPFL)。

输出执行所有请求后的\(S\)。

\(1\le N\le 2\times 10^5\)
\(|S|=2N\)
\(1\le Q\le 3\times 10^5\)
\(1\le T_i\le 2\),如果\(T_i=1\),\(1\le A_i < B_i\le 2N\);如果\(T_i=2\),\(A_i=B_i=0\)。

输入格式

\(N\)
\(S\)
\(Q\)
\(T_1~A_1~B_1\)
\(T_2~A_2~B_2\)
\(\hspace{18pt}\vdots\)
\(T_Q~A_Q~B_Q\)

样例

样例输入1

2
FLIP
2
2 0 0
1 1 4

样例输出1

LPFI

\(\text{FLIP}\to\text{IPFL}\to\text{LPFI}\)

样例输入2

2
FLIP
6
1 1 3
2 0 0
1 1 2
1 2 3
2 0 0
1 1 4

样例输出2

ILPF

分析

首先,\(\mathcal O(NQ)\)的模拟法肯定行不通,会TLE
我们考虑优化。
我们很容易发现,\(T_i=1\)的交换操作肯定是\(\mathcal O(1)\)的,但\(T_i=2\)的翻转操作是\(\mathcal O(n)\)的,所以需要优化。
我们可以用一个变量\(\mathrm{flipped}\)记录目前是否已经前后翻转(\(1\)表示已经翻转,\(0\)表示没有翻转),这时,操作变为如下:

  • 当\(T_i=2\),\(\mathrm{flipped}:=1-\mathrm{flipped}\);
  • 当\(T_i=1\)且\(\mathrm{flipped}=0\)时,我们直接交换\(A_i\)和\(B_i\)
  • 当\(T_i=\mathrm{flipped}=1\)时,我们发现,一个位置\(x\)如果\(<N\),则实际位置在\(x+N\);否则,实际位置在\(x-N\)。

这种算法的时间复杂度为\(\mathcal O(N+Q)\),可轻松通过此题。

代码

#include <cstdio>
#define maxn 400005
using namespace std;

char s[maxn];
int n;

inline void swap(char& x, char& y) { x ^= y ^= x ^= y; }
inline char& calc(int pos) { return s[pos < n? pos + n: pos - n]; }

int main()
{
	scanf("%d%s", &n, s);
	int q;
	scanf("%d", &q);
	bool flipped = false;
	while(q--)
	{
		int t, a, b;
		scanf("%d%d%d", &t, &a, &b);
		a --, b --;
		if(t == 2) flipped = !flipped;
		else if(flipped) swap(calc(a), calc(b));
		else swap(s[a], s[b]);
	}
	if(flipped)
		for(int i=0; i<n; i++)
			swap(s[i], s[n + i]);
	puts(s);
	return 0;
}

D - RGB Coloring 2

题目大意

我们有一个有\(N\)个点和\(M\)条边的简单无向图,第\(i\)条边连接着顶点\(A_i\)和\(B_i\)。
我们要给这个图用三种不同的颜色着色,使得相邻的顶点有不同的颜色。
有多少种合法的着色方法?不一定要使用所有颜色。

\(1\le N\le 20\)
\(0\le M\le \frac{N(N-1)}2\)
\(1\le A_i,B_i\le N\)

输入格式

\(N~M\)
\(A_1~B_1\)
\(A_2~B_2\)
\(\hspace{12pt}\vdots\)
\(A_M~B_M\)

输出格式

输出答案。

样例

样例输入1

3 3
1 2
2 3
3 1

样例输出1

6

我们用RGB分别代表三种不同的颜色,则有\(6\)中不同的着色方法,它们分别是RGBRBGGRBGBRBRGBGR

样例输入2

3 0

样例输出2

27

这个图没有边,所以任意着色都是可行的,一共有\(3^N=27\)种方法。

样例输入3

4 6
1 2
2 3
3 4
2 4
1 3
1 4

样例输出3

0

这里没有合法方案。

样例输入4

20 0

样例输出4

3486784401

分析

我们将图中的每个连通块依次暴力算出所有可能的着色方案数,再相乘即可。
其实,这里我们最大的总尝试数不是\(3^N\),而是\(3\times 2^{N-1}\),因为使用\(\text{DFS}\)时每个点的前一个点的颜色已经定好了,只需要尝试两种可能即可。

代码

似乎没人发现可以用unsigned int吧……

#include <cstdio>
#include <vector>
#define maxn 25
using namespace std;

vector<int> G[maxn];
int col[maxn], dep[maxn];

inline int next(int c) { return (c + 1) % 3; }

int paint(int v)
{
	for(int u: G[v])
		if(col[v] == col[u])
			return 0;
	int ans = 1;
	for(int u: G[v])
	{
		if(dep[u] == -1) dep[u] = dep[v] + 1;
		if(dep[u] == dep[v] + 1)
		{
			col[u] = next(col[v]);
			int res = paint(u);
			col[u] = next(col[u]);
			res += paint(u);
			col[u] = -1;
			if(res == 0) return 0;
			ans *= res;
		}
	}
	return ans;
}

int main()
{
	int n, m;
	scanf("%d%d", &n, &m);
	while(m--)
	{
		int x, y;
		scanf("%d%d", &x, &y);
		G[--x].push_back(--y);
		G[y].push_back(x);
	}
	for(int i=0; i<n; i++)
		col[i] = dep[i] = -1;
	unsigned int ans = 1;
	for(int i=0; i<n; i++)
		if(dep[i] == -1)
		{
			col[i] = dep[i] = 0;
			ans *= 3U * paint(i);
		}
	printf("%u\n", ans);
	return 0;
}

E - Permutation

题目大意

求符合如下条件的\((1,2,\dots,N)\)的排列的个数:

  • 对于每个\(1\le i\le M\),这个排列的前\(X_i\)个数中不超过\(Y_i\)的最多有\(Z_i\)个。

\(2\le N\le 18\)
\(0\le M\le 100\)
\(1\le X_i,Y_i < N\)
\(0\le Z_i < N\)

输入格式

\(N~M\)
\(X_1~Y_1~Z_1\)
\(X_2~Y_2~Z_2\)
\(\hspace{18pt}\vdots\)
\(X_M~Y_M~Z_M\)

输出格式

输出一个整数,即符合条件的排列的个数。

样例

样例输入1

3 1
2 2 1

样例输出1

4

四个符合条件的排列分别为:\((1,2,3)\)、\((2,3,1)\)、\((3,1,2)\)、\((3,2,1)\)。

样例输入2

5 2
3 3 2
4 4 3

样例输出2

90

样例输入3

18 0

样例输出3

6402373705728000

由于没有限制条件,所有的\(18!=6402373705728000\)个排列都可行。这也是本题的最大输出。

分析

首先,还是先排除\(\mathcal O(N!\sum X)\)的暴力算法,这样做的时间复杂度太高了。
我们考虑状压\(\text{DP}\)。令\(\mathrm{dp}_\mathrm{mask}\)表示从\((1,2,\dots,N)\)中选出子序列\(\mathrm{mask}\)(二进制第\(i\)位是\(0\)表示不选\(i\),\(1\)表示选\(i\))。
则,\(\mathrm{dp}_0=1\),动态转移方程为\(\mathrm{dp}_\mathrm{mask}=\mathrm{mask}\)中所有为的\(1\)位上把\(1\)变成\(0\)的\(\mathrm{dp}\)中的和,详见代码。
写代码时注意判断合法性,最终答案应为\(\mathrm{dp}_{2^N-1}\)(全选)。

代码

我这里做了一个小优化,即忽略\(Z_i\ge Y_i\)的条件。当然,我们也可以不用优化,但不能不用long long!!!

#include <cstdio>
#include <vector>
#define maxn 20
using namespace std;

using LL = long long;

vector<pair<int, int>> lim[maxn];
LL dp[1 << maxn];

int main()
{
	int n, m;
	scanf("%d%d", &n, &m);
	while(m--)
	{
		int x, y, z;
		scanf("%d%d%d", &x, &y, &z);
		if(z < y) lim[x].emplace_back(y, z);
	}
	int mx = 1 << n;
	dp[0] = 1LL;
	for(int st=0; st<mx; st++)
	{
		vector<int> s;
		for(int i=0; i<n; i++)
			if(st >> i & 1)
				s.push_back(i);
		int cnt = __builtin_popcount(st);
		bool ok = true;
		for(auto [y, z]: lim[cnt])
		{
			int tot = 0;
			for(auto x: s)
				if(x < y && ++tot > z)
				{
					ok = false;
					break;
				}
			if(!ok) break;
		}
		if(ok) for(int x: s) dp[st] += dp[st ^ (1 << x)];
	}
	printf("%lld\n", dp[mx - 1]);
	return 0;
}

标签:AtCoder,le,199,输出,int,题解,样例,输入,mathrm
From: https://www.cnblogs.com/stanleys/p/18403476/abc199

相关文章

  • KYOCERA Programming Contest 2021 (AtCoder Beginner Contest 200) A~E 题解
    A-Century题目大意公元\(N\)年在第几个世纪中?一个世纪是由\(100\)个年份组成的一个区间。如,\(1\)世纪为\([1,100]\)年,\(2\)世纪为\([101,200]\)年,……\(1\leN\le3000\)输入格式\(N\)输出格式将答案输出为一个整数。样例\(N\)输出\(2021\)\(21\)\(200......
  • AtCoder Beginner Contest 205 A~E 题解
    A-kcal题目大意我们有一种每\(100\)毫升含有\(A\)千卡热量的饮料。\(B\)毫升的这种饮料含有多少千卡热量?\(0\leA,B\le1000\)输入格式\(A~B\)输出格式输出\(B\)毫升这种饮料包含的的千卡数。最大允许浮点数精度误差\(10^{-6}\)。样例\(A\)\(B\)输出\(45\)......
  • AtCoder Beginner Contest 168 C~D 题解
    这次比赛的题名很特殊,是由符号+(+英文+)组成的......
  • AtCoder Beginner Contest 171 A~D 题解
    A-αlphabet题目大意输入一个英文字母\(a\),判断它是大写还是小写。输入格式\(a\)输出格式如果\(a\)为小写,输出a;如果\(a\)为大写,输出A。样例输入1B样例输出1AB为大写,所以输出A。样例输入2a样例输出2aa为小写,所以输出a。代码#include<cstdio>usingnames......
  • AtCoder Beginner Contest 187 A~D 题解
    A-LargeDigits题目大意给定两个三位整数\(A\)和\(B\),求它们数位和的最大值。数位和:例如,\(123\)的数位和是\(1+2+3=6\)。\(100\leA,B\le999\)输入格式\(A~~B\)输出格式一行,即\(A\)和\(B\)数位和的最大值。样例输入输出12323495939531710099927......
  • AtCoder Beginner Contest 173 A~D 题解
    A-Payment题目大意如果使用价值\(1000\)元的纸币(假设有)支付\(N\)元,服务员会找多少钱?\(1\leN\le10000\)输入格式\(N\)输出格式一行,即服务员找的钱数。样例输入输出190010030000分析特判:如果\(N\)除以\(1000\)能整除,那么不需要找钱,输出\(0\);如果......
  • Panasonic Programming Contest 2020 C (Sqrt Inequality) 题解
    题目大意输入三个整数\(a\),\(b\),\(c\),如果\(\sqrta+\sqrtb<\sqrtc\)成立,输出Yes,否则输出No。样例输入#1239输出#1No\(\sqrt2+\sqrt3<\sqrt9\)不成立。输入#22310输出#2Yes\(\sqrt2+\sqrt3<\sqrt10\)成立。分析错误思路首先,由......
  • AtCoder Beginner Contest 188 A~D 题解
    A-Three-PointShot题目大意有两个球队,分别得到\(X\)分和\(Y\)分,问得分较少的球队能否在获得三分后超越对方。\(0\leX,Y\le100\)\(X\neY\)\(X\)和\(Y\)都是整数。输入格式\(X~Y\)输出格式如果能,输出Yes;否则,输出No。样例XY输出35Yes分析这个不用......
  • AtCoder Beginner Contest 161D 题解
    原题链接:洛谷链接;AtCoder链接思路每次根据上一位,计算下一位为TA-1/TA/TA+1,放入queue中,最后输出第\(K\)次弹出的整数。注意事项不用longlong会WA!上一位为\(0\)时下一位不能为\(-1\)!(要特判)上一位为\(9\)时下一位不能为\(10\)!(也要特判)代码#include<cstdio>#include<que......
  • CodeForces Round #621 ABC (1307A+1307B+1307C) 题解
    A.CowandHaybales题面TheUSAConstructionOperation(USACO)recentlyorderedFarmerJohntoarrangearowofnhaybalepilesonthefarm.The\(i\)-thpilecontains\(a_i\)haybales.However,FarmerJohnhasjustleftforvacation,leavingBessieal......