1. 程式人生 > 其它 >【2021夏紀中游記】2021.8.13模擬賽

【2021夏紀中游記】2021.8.13模擬賽

比賽概括:

\(\mathrm{sum}=100+100+100+0\)

前三題都暴力還行。

T1 【NOIP2016提高A組模擬9.9】Brothers:

題目大意:

在遙遠的西方有一個古老的王國,國王將他的王國分成了網格狀,每一塊稱之為一個城市。在國王臨死前,他將這些城市分給了自己的N個兒子(編號為0到N-1)。然而這N個王子的關係不是很好,0討厭1,1討厭2,2討厭3……N-1討厭0。
在國王死後,這種不好的關係使得王子之間爆發了戰爭。戰鬥只會在相鄰的兩個城市之間爆發(共有一條邊稱之為相鄰),並且只有當A討厭B時,A才會對B發起戰鬥,結果必定是A獲得這次戰鬥的勝利。當一方勝利後,他所進攻的城市就會變成進攻方的。許多戰鬥是同時發生的,我們稱之為一場戰役。當多場戰役發生之後,剩下的王子將不再發生戰爭。

程式碼:

const int N = 110;

inline ll Read()
{
	ll x = 0, f = 1;
	char c = getchar();
	while (c != '-' && (c < '0' || c > '9')) c = getchar();
	if (c == '-') f = -f, c = getchar();
	while (c >= '0' && c <= '9') x = (x << 3) + (x << 1) + c - '0', c = getchar();
	return x * f;
}

int n, m, k, num;
int a[N][N], b[N][N];
int dx[4] = {0, 1, 0, -1}, dy[4] = {1, 0, -1, 0};

int main()
{
//	freopen(".in", "r", stdin);
//	freopen(".out", "w", stdout);
	num = Read(), n = Read(), m = Read(), k = Read();
	for (int i = 1; i <= n; i++)
		for (int j = 1; j <= m; j++)
			a[i][j] = Read();
	for (; k--; )
	{
		memcpy (b, a, sizeof b);
		for (int i = 1; i <= n; i++)
			for (int j = 1; j <= m; j++)
				for (int k = 0; k < 4; k++)
				{
					int x = i + dx[k], y = j + dy[k];
					if (x < 1 || x > n || y < 1 || y > m) continue;
					if (a[x][y] == (a[i][j] + 1) % num)
						b[x][y] = a[i][j];
				}
		memcpy (a, b, sizeof a);
	}
	for (int i = 1; i <= n; i++, puts(""))
		for (int j = 1; j <= m; j++)
			printf("%d ", a[i][j]);
	return 0;
}

T2 【NOIP2016提高A組模擬9.9】Crisis:

題目大意:

最近幾年,一場新的金融危機爆發了,這場危機使得很多人陷入的經濟問題的困境。一些X公司的員工試圖通過要求加薪度過這一難關。
X公司有著嚴格的等級制度,除了公司所有者小H以外,其他人都有一個直屬上司。沒有下屬的員工稱為工人,其他人則稱為領導者。
為了加薪,工人們都會向他們的上司提交請願書。當然,每個領導者都希望自己的下屬能夠儘可能快樂的工作,所以當至少有T%的下屬提交請願書時,那麼這個領導者就會向自己的上司提交請願書。計算百分比時,領導者只會計算直屬上司是他的下屬,當然,他也只會提交一次請願書。
如果最會小H收到了超過T%的請願書,那麼他將為所有工人們加薪。現在給出公司的構架和T的數值,你需要計算至少有多少工人提交請願書才能使得小H給工人加薪。

程式碼:

紀中機子日常爆棧。

const int N = 1e5 + 10;

inline ll Read()
{
	ll x = 0, f = 1;
	char c = getchar();
	while (c != '-' && (c < '0' || c > '9')) c = getchar();
	if (c == '-') f = -f, c = getchar();
	while (c >= '0' && c <= '9') x = (x << 3) + (x << 1) + c - '0', c = getchar();
	return x * f;
}

int n, t;
int cnt[N];

int head[N], tot;
struct edge
{
	int to, nxt;
}e[N];
void add(int u, int v)
{
	e[++tot] = (edge){v, head[u]}, head[u] = tot; 
}

int f[N], c[N];
int total = 0;
void dfs(int u)
{
	if (!cnt[u]) {f[u] = 1; return;}
	int son = ceil((double)cnt[u] * t / 100.0);
	for (int i = head[u]; i; i = e[i].nxt)
	{
		int v = e[i].to;
		dfs(v);
	}
	total = 0; 
	for (int i = head[u]; i; i = e[i].nxt)
		c[++total] = f[e[i].to];
	sort (c + 1, c + 1 + total);
	for (int i = 1; i <= son; i++) f[u] += c[i];
	return;
}

int main()
{
//	freopen(".in", "r", stdin);
//	freopen(".out", "w", stdout);
	n = Read(), t = Read();
	for (int i = 1; i <= n; i++)
	{
		int u = Read();
		add(u, i);
		cnt[u]++;
	}
	dfs(0);
	printf ("%d\n", f[0]);
	return 0;
}

T3 【NOIP2016提高A組模擬9.9】Word:

題目大意:

有k個字串{S1,S2,…,Sk},其中的每個字元不是空格,就是26個小寫英文字母中的一個。對於常數 l和d,我們的目標是從這k個字串中得出一個(l,d)-樣詞,它是一個長度為l的字串W=W[1]W[2]...W[l],它的每個字元必須符合下面的條件:
每個字串Si(i=1,2,…,k)都有一個長度為l的子串X=X[1]X[2]...X[l],X和W的出錯率小於或等於d。(X和W的出錯率是(X[j],W[j])的對數,其中,X[j]<>W[j],j=1,2,…,l)
在這個任務中,給你 l,d和一組字串;你要從中得出一個(l,d)-樣詞。你可以預設(l,d)-樣詞是存在的,而且是唯一的。
例1
如下3個字串,相對應的(3,0)-樣詞是“oil”:
oil is expensive
we have three oilers
be more oily

例2
如下4個字串,相對應的(5,1)-樣詞是“apple”:
you have two applas
i am an ppple
we are acples
adples are good for health

程式碼:


const int N = 60;

inline ll Read()
{
	ll x = 0, f = 1;
	char c = getchar();
	while (c != '-' && (c < '0' || c > '9')) c = getchar();
	if (c == '-') f = -f, c = getchar();
	while (c >= '0' && c <= '9') x = (x << 3) + (x << 1) + c - '0', c = getchar();
	return x * f;
}

int I, d, n;
int len[N];
char s[N][N];

void SolveD0()
{
	for (int l = 1; l + I - 1 <= len[1]; l++)
	{
		int r = l + I - 1, flag = 1;
		for (int i = 2; i <= n; i++)
		{
			int flag2 = 1;
			for (int l2 = 1; l2 + I - 1 <= len[i]; l2++)
			{
				flag2 = 1;
				for (int k = 1; k <= I; k++)
					if (s[1][l + k - 1] != s[i][l2 + k - 1])
					{
						flag2 = 0;
						break;
					}
				if (flag2) break;
			}
			if (!flag2) {flag = 0; break;}
		}
		if (flag)
		{
			for (int i = l; i <= r; i++)
				printf ("%c", s[1][i]);
			break;
		}
	}
}

void SolveD1()
{
	for (int l = 1; l + I - 1 <= len[1]; l++)
	{
		int r = l + I - 1, flag = 1;
		for (int u = l; u <= r; u++)
			for (int v = 1; v <= 27; v++)
			{
				flag = 1;
				char s1u = s[1][u];
				if (v == 27) s[1][u] = ' ';
				else s[1][u] = (char)'a' + v - 1;
				for (int i = 2; i <= n; i++)
				{
					int flag2 = 1;
					for (int l2 = 1; l2 + I - 1 <= len[i]; l2++)
					{
						flag2 = 1; int d = 0;
						for (int k = 1; k <= I; k++)
							if (s[1][l + k - 1] != s[i][l2 + k - 1])
							{
								if (d)
								{
									flag2 = 0;
									break;
								}
								else d++;
							}
						if (flag2) break;
					}
					if (!flag2) {flag = 0; break;}
				}
				if (flag)
				{
					for (int i = l; i <= r; i++)
						printf ("%c", s[1][i]);
					return;
				}
				s[1][u] = s1u;
			}
		}
}

void SolveD2()
{
	for (int l = 1; l + I - 1 <= len[1]; l++)
	{
		int r = l + I - 1, flag = 1;
		for (int u = l; u <= r; u++)
			for (int v = 1; v <= 27; v++)
				for (int u2 = l; u2 <= r; u2++)
					for (int v2 = 1; v2 <= 27; v2++)
					{
						flag = 1;
						char s1u = s[1][u], s1u2 = s[1][u2];
						if (v == 27) s[1][u] = ' ';
						else s[1][u] = (char)'a' + v - 1;
						if (v2 == 27) s[1][u2] = ' ';
						else s[1][u2] = (char)'a' + v2 - 1;
						for (int i = 2; i <= n; i++)
						{
							int flag2 = 1;
							for (int l2 = 1; l2 + I - 1 <= len[i]; l2++)
							{
								flag2 = 1; int d = 0;
								for (int k = 1; k <= I; k++)
									if (s[1][l + k - 1] != s[i][l2 + k - 1])
									{
										if (d == 2)
										{
											flag2 = 0;
											break;
										}
										else d++;
									}
								if (flag2) break;
							}
							if (!flag2) {flag = 0; break;}
						}
						if (flag)
						{
							for (int i = l; i <= r; i++)
								printf ("%c", s[1][i]);
							return;
						}
						s[1][u] = s1u;
						s[1][u2] = s1u2;
					}
				}
}

int main()
{
//	freopen(".in", "r", stdin);
//	freopen(".out", "w", stdout);
	I = Read(), d = Read(), n = Read();
	for (int i = 1; i <= n; i++)
	{
		s[i][++len[i]] = getchar();
		while (s[i][len[i]] != ' ' && (s[i][len[i]] < 'a' || s[i][len[i]] > 'z')) 
			s[i][len[i]] = getchar();
		while (s[i][len[i]] == ' ' || (s[i][len[i]] >= 'a' && s[i][len[i]] <= 'z'))
			s[i][++len[i]] = getchar();
		len[i]--;
	}
	if (d == 0) SolveD0();
	if (d == 1) SolveD1();
	if (d == 2) SolveD2();
	return 0;
}

T4 graph:

原題見【Luogu P5787】二分圖 /【模板】線段樹分治