A
令\[C_i=\min_{j>i,s_j=s_i}\{j-i\}\],则题目中所说的B-Suffix Array等价于\(C_1,C_2,C_3,...,C_n\)。因此,只需要求出\(C\)后,对\(C\)算一下后缀数组即可。
代码如下:
#include <algorithm>
#include <cctype>
#include <cmath>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <map>
#include <queue>
#include <set>
#include <stack>
#include <string>
#include <unordered_map>
#include <vector>
#define mst(a, b) memset((a), (b), sizeof(a))
#define debug printf("debug\n")
#define INF 0x3f3f3f3f
#define lson lef, mid, rt << 1
#define rson mid + 1, rig, rt << 1 | 1
const int maxn = 1e5 + 5;
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
int wa[maxn], wb[maxn], wv[maxn], wss[maxn], rak[maxn], height[maxn], cal[maxn], n, sa[maxn << 1];
char s[maxn];
int cmp(int* r, int a, int b, int l)
{
return r[a] == r[b] && r[a + l] == r[b + l];
}
void da(int* r, int* sa, int n, int M)
{
int i, j, p, *x = wa, *y = wb, *t;
for (i = 0; i < M; i++)
wss[i] = 0;
for (i = 0; i < n; i++)
wss[x[i] = r[i]]++;
for (i = 1; i < M; i++)
wss[i] += wss[i - 1];
for (i = n - 1; i >= 0; i--)
sa[--wss[x[i]]] = i;
for (j = 1, p = 1; p < n; j <<= 1, M = p) {
for (p = 0, i = n - j; i < n; i++)
y[p++] = i;
for (i = 0; i < n; i++)
if (sa[i] >= j)
y[p++] = sa[i] - j;
for (i = 0; i < n; i++)
wv[i] = x[y[i]];
for (i = 0; i < M; i++)
wss[i] = 0;
for (i = 0; i < n; i++)
wss[wv[i]]++;
for (i = 1; i < M; i++)
wss[i] += wss[i - 1];
for (i = n - 1; i >= 0; i--)
sa[--wss[wv[i]]] = y[i];
for (t = x, x = y, y = t, p = 1, x[sa[0]] = 0, i = 1; i < n; i++)
x[sa[i]] = cmp(y, sa[i - 1], sa[i], j) ? p - 1 : p++;
}
return;
}
int main()
{
//freopen("./A.in", "r", stdin);
while (scanf("%d", &n) != EOF) {
fill(cal, cal + maxn, 0);
scanf("%s", s + 1);
int pre[2] = { n + 1, n + 1 };
for (int i = n; i >= 1; i--) {
if (pre[s[i] - 'a'] == n + 1) {
cal[i] = n;
} else {
cal[i] = pre[s[i] - 'a'] - i;
}
pre[s[i] - 'a'] = i;
}
cal[n + 1] = n + 1;
//puts("cal: ");
//for (int i = 1; i <= n + 1; i++) {
// printf("%d ",cal[i]);
//}
//puts("");
//puts("----------------------");
da(cal + 1, sa, n + 2, n + 2);
for (int i = n; i >= 1; i--) {
printf("%d%c", sa[i] + 1, i == 1 ? '\n' : ' ');
}
}
return 0;
}
这道题\(n\)的值一定要是\(n+2\),\(m\)的值一定也要是\(n+2\)!否则不是RE就是WA!
B
待补
C
待补
D
待补
E
待补
F
假设两个字符串\(a,b\)是同一个字符串的循环节,然后在\(2\times max(len(a),len(b))\)的范围内比较即可。如果发现没有不相等的字符,则说明两个无穷字符串是同一个字符串,也就是相等。否则,如果\(a_i<b_i\),则\(a<b\);大于的情况同理。这道题的比较范围比较玄学,是猜出来的,但根据题解,范围只需要到\(len(a)+len(b)-gcd(len(a),len(b))\)即可。但目前没想明白为什么。。。等一波详细题解。
#include <algorithm>
#include <cctype>
#include <cmath>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <map>
#include <queue>
#include <set>
#include <stack>
#include <string>
#include <unordered_map>
#include <vector>
#define mst(a, b) memset((a), (b), sizeof(a))
#define debug printf("debug\n")
#define INF 0x3f3f3f3f
#define lson lef, mid, rt << 1
#define rson mid + 1, rig, rt << 1 | 1
const int maxn = 1e5 + 5;
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
int main()
{
string sa, sb;
std::ios::sync_with_stdio(0);
while (cin >> sa >> sb) {
int lena = sa.size();
int lenb = sb.size();
int bnd = 2 * max(lena, lenb);
int ans = 0;
for (int i = 0; i < bnd; i++) {
if (sa[i % lena] < sb[i % lenb]) {
ans = 1; // <
break;
} else if (sa[i % lena] > sb[i % lenb]) {
ans = 2; // >
break;
}
}
cout << "=<>"[ans] << "\n";
}
return 0;
}
G
待补
H
题意是说,给定一个\(n\)个点\(m\)条边的流网络,有\(q\)次询问,第\(i\)次询问会把图上所有边的容量都设为\(\frac{u_i}{v_i}\),查询当前情况下,从点1发送一个单位的流到点\(n\)的最小花费是多少。
为了方便处理,将所有边的容量都乘以\(\frac{v_i}{u_i}\),使其变成1;原本发送一个单位的流,现在变成发送\(\frac{v_i}{u_i}\)个单位的流(实际上就相当于定义了一个新单位,该单位和原单位的进率是\(\frac{v_i}{u_i}\))。然后在算最大流的时候,再记录下不同流量下的最小花费。
而NaN的情况有两种:
- \(u=0\)(不考虑这种情况会有除零错误)
- \(v/u>\)最大流(非整除)
最后,注意一下处理最终答案的方法(代码165行)
代码如下:
#include <algorithm>
#include <cctype>
#include <cmath>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <map>
#include <queue>
#include <set>
#include <stack>
#include <string>
#include <unordered_map>
#include <vector>
#define mst(a, b) memset((a), (b), sizeof(a))
#define debug printf("debug\n")
#define INF 0x3f3f3f3f
#define lson lef, mid, rt << 1
#define rson mid + 1, rig, rt << 1 | 1
const int maxn = 100 + 5;
const int maxm = 200 + 5;
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
struct edge {
int to;
int nxt;
int cap;
int flow;
int cost;
} es[maxm];
int head[maxn];
int tol;
int pre[maxn], dis[maxn];
bool vis[maxn];
ll ansarr[maxm];
int N; // 节点总个数, 节点从0~N-1
int M;
inline void init(int n)
{
N = n;
tol = 0;
mst(head, -1);
}
inline void addedge(int u, int v, int cap, int cost)
{
es[tol].to = v;
es[tol].cap = cap;
es[tol].cost = cost;
es[tol].flow = 0;
es[tol].nxt = head[u];
head[u] = tol++;
es[tol].to = u;
es[tol].cap = 0;
es[tol].cost = -cost;
es[tol].flow = 0;
es[tol].nxt = head[v];
head[v] = tol++;
}
bool spfa(int s, int t)
{
queue<int> que;
for (int i = 0; i < N; i++) {
dis[i] = INF;
vis[i] = false;
pre[i] = -1;
}
dis[s] = 0;
vis[s] = true;
que.push(s);
while (!que.empty()) {
int u = que.front();
que.pop();
vis[u] = false;
for (int i = head[u]; i != -1; i = es[i].nxt) {
int v = es[i].to;
if (es[i].cap > es[i].flow && dis[v] > dis[u] + es[i].cost) {
dis[v] = dis[u] + es[i].cost;
pre[v] = i;
if (!vis[v]) {
vis[v] = true;
que.push(v);
}
}
}
}
if (pre[t] == -1)
return false;
else
return true;
}
ll mcmf(int s, int t, ll& cost)
{
ll flow = 0;
cost = 0;
while (spfa(s, t)) {
ll Min = INF;
for (int i = pre[t]; i != -1; i = pre[es[i ^ 1].to]) {
if (Min > es[i].cap - es[i].flow) {
Min = es[i].cap - es[i].flow;
}
}
for (int i = pre[t]; i != -1; i = pre[es[i ^ 1].to]) {
es[i].flow += Min;
es[i ^ 1].flow -= Min;
cost += es[i].cost * Min;
}
flow += Min;
ansarr[(int)flow] = cost;
}
return flow;
}
inline int read()
{
char ch;
int x = 0;
int sign = 1;
do {
ch = getchar();
if (ch == '-')
sign = -1;
} while (ch > '9' || ch < '0');
while ('0' <= ch && ch <= '9') {
x = (x << 3) + (x << 1) + (ch - '0');
ch = getchar();
}
return x * sign;
}
ll gcd(ll a, ll b)
{
return b == 0 ? a : gcd(b, a % b);
}
//inline void Swap(ll& a,ll& b)
//{
//ll tmp=a;
//a=b;b=tmp;
//}
int main()
{
while (scanf("%d %d", &N, &M) != EOF) {
init(N);
int ai, bi, ci;
for (int i = 0; i < M; i++) {
ai = read();
bi = read();
ci = read();
ai--;
bi--;
addedge(ai, bi, 1, ci);
}
ll miniflow;
ll maxiflow = mcmf(0, N - 1, miniflow);
int q;
q = read();
int u, v;
while (q--) {
u = read();
v = read();
//printf("maxiflow = %lld\n",maxiflow);
if (u == 0 || ((1LL * v) / u == maxiflow && (1LL * v) % u > 0) || (1LL * v) / u > maxiflow) {
puts("NaN");
continue;
}
int idx = v / u;
ll up = ansarr[idx] * u + (ansarr[idx + 1] - ansarr[idx]) * (v % u);
//if(v<up) Swap(v, up)
ll g = gcd(1LL * v, up);
printf("%lld/%lld\n", up / g, v / g);
}
}
return 0;
}
I
待补
J
高数签到题。虽然这题是我A的,但是因为高数太菜,所以其实积分结果是在OEIS上找到的hhh。
积分过程如下: \[ \begin{aligned} \because (x-x^2)^n&=\frac{1}{4}-\left( \frac{1}{2}-x\right )^2 \\ \therefore \int_0^1(x-x^2)^ndx&=\int_0^1\left(\frac{1}{4}-\left(\frac{1}{2}-x\right)^2\right)^ndx\\ &=\frac{1}{4^n}\int_0^1\left(1-4\left(\frac{1}{2}-x\right)^2\right)^ndx\\ &=\frac{1}{4^n}\int_0^1\left(1-(2x-1)^2\right)^ndx \end{aligned} \] 令\(\sin t=2x-1\),则有 \[ \begin{aligned} \int_0^1(x-x^2)^ndx&=\frac{1}{4^n}\int_{-\frac{\pi}{2}}^{\frac{\pi}{2}}(1-\sin^2t)^ndx\\ &=\frac{1}{4^n}\int_{-\frac{\pi}{2}}^{\frac{\pi}{2}}(1-\sin^2t)^n\frac{\cos t}{2}dt\\ &=\frac{1}{4^n}\int_0^{\frac{\pi}{2}}\cos^{2n+1}tdt \end{aligned} \]
由Wallis公式: \[ \int_0^{\frac{\pi}{2}}\cos^nxdx= \begin{cases} \frac{\pi(2k)!!}{2(2k+1)!!}&\text{n=2k}\\ \frac{(2k)!!}{(2k+1)!!}&\text{n=2k+1} \end{cases} \] 其中,\(\frac{(2k)!!}{(2k+1)!!}=\frac{2\times4\times6\times\dots\times(2n-2)\times2n}{1\times3\times5\times\dots\times(2n-1)\times(2n+1)}\)。因此,有 \[ \begin{aligned} \int_0^1(x-x^2)^ndx&=\frac{1}{4^n}\frac{(2n)!!}{(2n+1)!!}\\ &=\frac{1}{4^n}\frac{(2n)!!}{\frac{(2n+1)!}{(2n)!!}}\\ &=\frac{1}{4^n}\frac{(2n!!)^2}{(2n+1)!}\\ &=\frac{1}{4^n}\frac{4^n(n!)^2}{(2n+1)!}\\ &=\frac{(n!)^2}{(2n+1)!} \end{aligned} \] 得到上面的积分结果后,套式子再求个逆元就行了。
代码如下:
#include <algorithm>
#include <cctype>
#include <cmath>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <map>
#include <queue>
#include <set>
#include <stack>
#include <string>
#include <unordered_map>
#include <vector>
#define mst(a, b) memset((a), (b), sizeof(a))
#define debug printf("debug\n")
#define INF 0x3f3f3f3f
#define lson lef, mid, rt << 1
#define rson mid + 1, rig, rt << 1 | 1
const int maxn = 1e5 + 5;
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int bnd = 2e6 + 2;
const ll mod = 998244353;
ll frac[bnd];
inline void init()
{
frac[0] = frac[1] = 1;
for (int i = 2; i <= bnd; i++) {
frac[i] = (frac[i - 1] % mod * i % mod) % mod;
}
}
ll exgcd(ll a, ll b, ll& x, ll& y)
{
if (a == 0 && b == 0) {
return -1;
}
if (b == 0) {
x = 1;
y = 0;
return a;
}
ll d = exgcd(b, a % b, y, x);
y -= a / b * x;
return d;
}
ll inv(ll a, ll n)
{
ll x, y;
ll d = exgcd(a, n, x, y);
if (d == 1)
return (x % n + n) % n;
else
return -1;
}
int main()
{
init();
ll n;
while (scanf("%lld", &n) != EOF) {
ll f = frac[n];
ll ff = frac[2 * n + 1];
ll up = (f % mod * f % mod) % mod;
ll down = ff % mod;
ll ans = (up % mod * inv(down, mod) % mod) % mod;
printf("%lld\n", ans);
}
return 0;
}