A B-Suffix Array

题意;

将字符串 2020牛客暑期多校训练营(第一场)_数组 的每个后缀化成 2020牛客暑期多校训练营(第一场)_ci_02 数组,然后对 2020牛客暑期多校训练营(第一场)_ci_02 数组进行字典序排序。
那个定义的规则就是找前面和他相同字符的最近距离,否则为 2020牛客暑期多校训练营(第一场)_字符串_04

2020牛客暑期多校训练营(第一场)_数组_05 相当于后面的最近的与 2020牛客暑期多校训练营(第一场)_数组_06 相同的字符到 2020牛客暑期多校训练营(第一场)_数组_07

对于不存在这样的 2020牛客暑期多校训练营(第一场)_ci_082020牛客暑期多校训练营(第一场)_数组_05,我们要让他比其他 2020牛客暑期多校训练营(第一场)_数组_05 都大,设为 2020牛客暑期多校训练营(第一场)_字符串_11,然后最后再放一个 2020牛客暑期多校训练营(第一场)_字符串_122020牛客暑期多校训练营(第一场)_字符串_13 的末尾,最后求出 2020牛客暑期多校训练营(第一场)_字符串_13 的后缀数组,去掉最后一位倒着输出就是答案。

2020牛客暑期多校训练营(第一场)_数组_15


2020牛客暑期多校训练营(第一场)_ci_16

AC代码:

const int N = 1e5 + 50;
int n, s[N];
char S[N];
int fir[N], sec[N], sa[N], c[N];
void get_SA()
{
int m = n;
rep(i, 1, n)
c[fir[i] = s[i]]++;
rep(i, 2, m)
c[i] += c[i - 1];
per(i, n, 1)
sa[c[fir[i]]--] = i;
for (int k = 1, tot; k < n; k <<= 1)
{
tot = 0;
rep(i, n - k + 1, n)
sec[++tot] = i;
rep(i, 1, n) if (sa[i] > k)
sec[++tot] = sa[i] - k;
rep(i, 1, m)
c[i] = 0;
rep(i, 1, n)
c[fir[i]]++;
rep(i, 2, m)
c[i] += c[i - 1];
per(i, n, 1)
sa[c[fir[sec[i]]]--] = sec[i];
rep(i, 1, n)
swap(fir[i], sec[i]);
fir[sa[1]] = tot = 1;
rep(i, 2, n) if (sec[sa[i]] == sec[sa[i - 1]] && sec[sa[i] + k] == sec[sa[i - 1] + k])
fir[sa[i]] = tot;
else fir[sa[i]] = ++tot;
if (tot == n)
break;
m = tot;
}
}

int main()
{
while (~sd(n))
{
ss(S + 1);
rep(i, 1, n)
{
rep(j, i + 1, n)
{
if (S[j] == S[i])
{
s[i] = j - i;
break;
}
}
if (!s[i])
s[i] = n;
}
n++;
s[n] = n;
get_SA();
per(i, n - 1, 1)
printf("%d ", sa[i]);
printf("\n");
rep(i, 1, n)
s[i] = fir[i] = sec[i] = sa[i] = c[i] = 0;
}
}

F Infinite String Comparision

题意:

给定两个字符串 2020牛客暑期多校训练营(第一场)_ci_17。比较无限个字符串 2020牛客暑期多校训练营(第一场)_字符串_18 拼接和无限个字符串 2020牛客暑期多校训练营(第一场)_ci_19

先把长的串复制两次,然后把短的串变成复制或长串的长度直接比较就行了。

AC代码:

const int N = 1e6 + 50;
int n, m, k, x;
string a, b;
int main()
{
int t;
while (cin >> a >> b)
{
int len1 = a.size();
int len2 = b.size();
if (len1 == len2)
{
if (a == b)
puts("=");
else if (a < b)
puts("<");
else
puts(">");
}
else if (len1 < len2)
{
b += b;
len2 += len2;
string s = a;
int len = len1;
while (len + len1 <= len2)
{
s += a;
len += len1;
}
if (len < len2)
{
int res = len2 - len;
rep(i, 0, res - 1)
s += a[i];
}
//cout<<s<<endl;
//cout<<b<<endl;
if (s == b)
puts("=");
else if (s < b)
puts("<");
else
puts(">");
}
else
{
a += a;
len1 += len1;
string s = b;
int len = len2;
while (len + len2 <= len1)
{
s += b;
len += len2;
}
if (len < len1)
{
int res = len1 - len;
rep(i, 0, res - 1)
s += b[i];
}
//cout<<a<<endl;
//cout<<s<<endl;
if (s == a)
puts("=");
else if (s < a)
puts(">");
else
puts("<");
}
}
return 0;
}

J Easy Integration

题意;

给定一个 2020牛客暑期多校训练营(第一场)_ci_20,求 2020牛客暑期多校训练营(第一场)_数组_21

2020牛客暑期多校训练营(第一场)_数组_22

2020牛客暑期多校训练营(第一场)_ci_23

2020牛客暑期多校训练营(第一场)_字符串_24

2020牛客暑期多校训练营(第一场)_字符串_25

2020牛客暑期多校训练营(第一场)_ci_26

2020牛客暑期多校训练营(第一场)_字符串_27

2020牛客暑期多校训练营(第一场)_字符串_28

AC代码:

ll mult(ll x, ll y, ll mod)
{
return (x * y - (ll)(x / (long double)mod * y + 1e-3) * mod + mod) % mod;
}

const int N = 2e6 + 50;
const int mod = 998244353;
int n, m, k, x;
ll f[N];

void init()
{
f[0] = 0;
f[1] = 1;
rep(i, 2, N - 10)
f[i] = mult(f[i - 1], i, mod);
}

int main()
{
init();
while (~sd(n))
{
ll ans = mult(qpow(f[n], 2, mod), qpow(f[2 * n + 1], mod - 2, mod), mod);
pld(ans);
}
return 0;
}