题面
2
≤
L
≤
R
≤
1
0
7
2\leq L\leq R\leq10^7
2≤L≤R≤107
题解
题目相当于求“泡冒”的总时间,我们对于每个数字求贡献。
我们发现,每次“泡冒”,一个数 p i p_i pi 前面比它大的数如果有,必定减少一个,否则令后面最后一个比 p i p_i pi 小的数为 p j p_j pj , [ i , j ) [i,j) [i,j) 区间内大于等于 p i p_i pi 的数将减少一个(包括自己)。
所以,我们可以先计算 p i p_i pi 前面比它大的数个数的总贡献,再计算 [ i , j ) [i,j) [i,j) 内的贡献。
前者是老经典问题了,递推式很简单,令
f
(
x
)
f(x)
f(x) 表示长度为
x
x
x 的排列的答案,那么枚举最后一个数的逆序对个数:
f
(
x
)
=
f
(
x
−
1
)
⋅
x
+
x
!
⋅
x
(
x
−
1
)
2
f
(
1
)
=
0
f(x)=f(x-1)\cdot x+x!\cdot\frac{x(x-1)}{2}\\ f(1)=0
f(x)=f(x−1)⋅x+x!⋅2x(x−1)f(1)=0
对于后者,我们可以考虑枚举
[
i
,
j
)
[i,j)
[i,j) 内大于等于
p
i
p_i
pi 的数的贡献。若存在
i
≤
k
,
j
>
k
i\leq k,j>k
i≤k,j>k 满足
p
j
<
p
i
≤
p
k
p_j<p_i\leq p_k
pj<pi≤pk ,那么
p
k
p_k
pk 就对
p
i
p_i
pi 产生一次贡献。对于这个问题,之前「枚举最后一个数的贡献」的转移方法不太适用,我们需要换一个思路——枚举最大的数的贡献。我们令
g
(
x
)
g(x)
g(x) 表示长度为
x
x
x 的排列的答案,枚举最大的数
p
k
=
x
p_k=x
pk=x 的位置,计算左边每个数的贡献。对于
k
k
k ,贡献是 1,对于左边的
k
−
1
k-1
k−1 个数,有
x
−
k
x
−
k
+
1
\frac{x-k}{x-k+1}
x−k+1x−k 的概率产生贡献,因此
g
(
x
)
=
g
(
x
−
1
)
⋅
x
+
(
x
−
1
)
!
(
x
−
1
+
∑
i
=
1
x
−
1
i
i
+
1
⋅
(
x
−
i
−
1
)
)
=
g
(
x
−
1
)
⋅
x
+
(
x
−
1
)
!
(
x
−
1
+
∑
i
=
1
x
−
1
(
i
x
i
+
1
−
i
)
)
=
g
(
x
−
1
)
⋅
x
+
(
x
−
1
)
!
(
x
−
1
+
x
∑
i
=
1
x
−
1
(
1
−
1
i
+
1
)
−
∑
i
=
1
x
−
1
i
)
=
g
(
x
−
1
)
⋅
x
+
(
x
−
1
)
!
(
x
−
1
+
x
(
x
−
1
)
−
∑
i
=
1
x
−
1
1
i
+
1
−
∑
i
=
1
x
−
1
i
)
=
g
(
x
−
1
)
⋅
x
+
(
x
−
1
)
!
(
x
−
1
+
x
(
x
−
1
)
2
−
∑
i
=
1
x
−
1
1
i
+
1
)
g(x)=g(x-1)\cdot x+(x-1)!(x-1+\sum_{i=1}^{x-1}\frac{i}{i+1}\cdot(x-i-1))\\ =g(x-1)\cdot x+(x-1)!(x-1+\sum_{i=1}^{x-1}(\frac{ix}{i+1}-i))\\ =g(x-1)\cdot x+(x-1)!(x-1+x\sum_{i=1}^{x-1}(1-\frac{1}{i+1})-\sum_{i=1}^{x-1}i)\\ =g(x-1)\cdot x+(x-1)!(x-1+x(x-1)-\sum_{i=1}^{x-1}\frac{1}{i+1}-\sum_{i=1}^{x-1}i)\\ =g(x-1)\cdot x+(x-1)!(x-1+\frac{x(x-1)}{2}-\sum_{i=1}^{x-1}\frac{1}{i+1})\\
g(x)=g(x−1)⋅x+(x−1)!(x−1+i=1∑x−1i+1i⋅(x−i−1))=g(x−1)⋅x+(x−1)!(x−1+i=1∑x−1(i+1ix−i))=g(x−1)⋅x+(x−1)!(x−1+xi=1∑x−1(1−i+11)−i=1∑x−1i)=g(x−1)⋅x+(x−1)!(x−1+x(x−1)−i=1∑x−1i+11−i=1∑x−1i)=g(x−1)⋅x+(x−1)!(x−1+2x(x−1)−i=1∑x−1i+11)
右边的
∑
1
i
+
1
\sum \frac{1}{i+1}
∑i+11 可以预处理出来,于是这道题就做完了,时间复杂度
O
(
R
)
O(R)
O(R) ,答案是
⨁
i
=
L
R
(
f
(
i
)
+
g
(
i
)
m
o
d
998244353
)
\bigoplus_{i=L}^R (f(i)+g(i)\mod 998244353)
i=L⨁R(f(i)+g(i)mod998244353)
CODE
#include<map>
#include<set>
#include<cmath>
#include<queue>
#include<stack>
#include<random>
#include<vector>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
#define MAXN 10000005
#define LL long long
#define ULL unsigned long long
#define ENDL putchar('\n')
#define DB double
#define lowbit(x) (-(x) & (x))
#define FI first
#define SE second
int xchar() {
static const int maxn = 1000000;
static char b[maxn];
static int pos = 0,len = 0;
if(pos == len) pos = 0,len = fread(b,1,maxn,stdin);
if(pos == len) return -1;
return b[pos ++];
}
//#define getchar() xchar()
LL read() {
LL f = 1,x = 0;int s = getchar();
while(s < '0' || s > '9') {if(s<0)return -1;if(s=='-')f=-f;s = getchar();}
while(s >= '0' && s <= '9') {x = (x<<1) + (x<<3) + (s^48);s = getchar();}
return f*x;
}
void putpos(LL x) {if(!x)return ;putpos(x/10);putchar((x%10)^48);}
void putnum(LL x) {
if(!x) {putchar('0');return ;}
if(x<0) putchar('-'),x = -x;
return putpos(x);
}
void AIput(LL x,int c) {putnum(x);putchar(c);}
const int MOD = 998244353;
const int inv2 = (MOD+1)/2,inv3 = (MOD+1)/3,inv4 = inv2*1ll*inv2%MOD,inv6 = inv2*1ll*inv3%MOD;
int n,m,s,o,k;
int fac[MAXN],dp[MAXN],dp2[MAXN],invs[MAXN];
int main() {
freopen("tros.in","r",stdin);
freopen("tros.out","w",stdout);
n = read();m = read();
fac[0] = fac[1] = 1; invs[0] = invs[1] = 1;
for(int i = 2;i <= m+1;i ++) {
fac[i] = fac[i-1] *1ll* i % MOD;
invs[i] = (MOD-invs[MOD%i]) *1ll* (MOD/i) % MOD;
}
for(int i = 2;i <= m+1;i ++) {
(invs[i] += invs[i-1]) %= MOD;
}
dp[1] = 0;
for(int i = 2;i <= m;i ++) {
dp[i] = (dp[i-1]*1ll*i%MOD + ((i-1)*1ll*i/2)%MOD*fac[i-1]%MOD) % MOD;
dp2[i] = (dp2[i-1]*1ll*i%MOD + (i-1+i*1ll*(i-1)/2+MOD-(invs[i]+MOD-invs[1])%MOD*1ll*i%MOD)%MOD*1ll*fac[i-1]%MOD) % MOD;
}
int ans = 0;
for(int i = n;i <= m;i ++) ans ^= (dp[i]+dp2[i])%MOD;
AIput(ans,'\n');
return 0;
}