547 篇文章 2 订阅
51 篇文章 0 订阅
280 篇文章 1 订阅

# 题目

R e m i n d e r \rm Reminder ：后缀数组 s a sa 满足，将一个字符串的所有后缀 l e x i c o g r a p h i c a l l y \rm lexicographically 排序，排在第 i i 位的是 s a i sa_i 开头的后缀。或者直白一点：对于任意 i < j i<j 都成立 s [ s a i ∼ n ] < s [ s a j ∼ n ] s[sa_i\sim n]<s[sa_j\sim n] ，这里是字典序比较。

n ≤ 2 × 1 0 5 n\le 2\times 10^5 。狡猾的出题人告诉你 k ≤ 2 × 1 0 5 k\le 2\times 10^5 ，理由是

Btw k was chosen to also be ≤ 2 × 1 0 5  so as to hide the final complexity \text{Btw k was chosen to also be}≤2×10^5\text{ so as to hide the final complexity} 😃

# 思路

[ x k ]    F ( x ) p ⋅ [ F ( x ) − 1 ] q [x^k]\;F(x)^{p}\cdot[F(x)-1]^{q}

[ x k ]    F ( x ) p ⋅ [ F ( x ) − 1 ] q = [ x k ]    ( 1 − x k + 1 1 − x ) p ( x − x k + 1 1 − x ) q = [ x k ]    x q ( 1 − x ) p + q = [ x k − q ]    1 ( 1 − x ) p + q = ( p + k − 1 p + q − 1 ) [x^k]\;F(x)^p\cdot [F(x)-1]^{q}\\ =[x^k]\;\left(\frac{1-x^{k+1}}{1-x}\right)^p\left(\frac{x-x^{k+1}}{1-x}\right)^q\\ =[x^k]\;\frac{x^q}{(1-x)^{p+q}}\\ =[x^{k-q}]\;{1\over (1-x)^{p+q}}\\ ={p+k-1\choose p+q-1}

D D G \sf DDG 还有一种做法，直接枚举有多少种字母，然后在那些 ≥ \ge 的位置中找到一些分界点。形如 ∑ i = q p + q ( p i − q ) ( k i ) \sum_{i=q}^{p+q}{p\choose i-q}{k\choose i} ，确实更容易想一些。常数肯定不优秀

# 代码

#include <cstdio>
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
# define rep(i,a,b) for(int i=(a); i<=(b); ++i)
# define drep(i,a,b) for(int i=(a); i>=(b); --i)
typedef long long int_;
int a = 0; char c = getchar(), f = 1;
for(; c<'0'||c>'9'; c=getchar())
if(c == '-') f = -f;
for(; '0'<=c&&c<='9'; c=getchar())
a = (a<<3)+(a<<1)+(c^48);
return a*f;
}

const int Mod = 998244353;
const int MaxN = 400005;
int sa[MaxN], rnk[MaxN];
int_ inv[MaxN]; // int_ is good
int main(){
for(int i=1; i<=n; ++i){
rnk[sa[i]] = i;
}
rnk[n+1] = 0; // smallest
int cnt0 = 0, cnt1 = 0, ans;
for(int i=2; i<=n; ++i)
if(rnk[sa[i-1]+1] > rnk[sa[i]+1])
++ cnt1; // strictly greater
else ++ cnt0; // greater or equal
++ cnt1, ++ cnt0; // origin & sum
int N = k+cnt0-1, M = cnt0+cnt1-1;
rep(i,(ans=1)+(inv[1]=1),M){
inv[i] = (Mod-Mod/i)*inv[Mod%i]%Mod;
ans = ans*inv[i]%Mod; // div M!
}
rep(i,1,M) ans = ans*(N+1ll-i)%Mod;
if(N < M) ans = 0; // bad combination
printf("%d\n",ans);
return 0;
}

02-27 5425
08-11 46
05-30 167
03-06
08-26
01-03 5174
02-09 1566

• 非常没帮助
• 没帮助
• 一般
• 有帮助
• 非常有帮助