【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;
}