首先让我们考虑一下答案的表达式。
设当前的询问区间为 [ L e f t , R i g h t ] [Left,Right] [Left,Right],且在当前区间中第 i i i种袜子有 N u m [ i ] Num[i] Num[i]支,那么 A n s = C N u m [ 1 ] 2 + C N u m [ 2 ] 2 + C N u m [ 3 ] + . . . 2 C R i g h t + 1 − L e f t 2 Ans=\frac{C^2_{Num[1]}+C^2_{Num[2]}+C^2_{Num[3]+...}}{C^2_{Right+1-Left}} Ans=CRight+1−Left2CNum[1]2+CNum[2]2+CNum[3]+...2
令 L e n g t h = R i g h t + 1 − L e f t Length=Right+1-Left Length=Right+1−Left
展开组合数:
A
n
s
=
N
u
m
[
1
]
2
+
N
u
m
[
2
]
2
+
N
u
m
[
3
]
2
+
.
.
.
−
L
e
n
g
t
h
L
e
n
g
t
h
∗
(
L
e
n
g
t
h
−
1
)
Ans=\frac{Num[1]^2+Num[2]^2+Num[3]^2+...-Length}{Length*(Length-1)}
Ans=Length∗(Length−1)Num[1]2+Num[2]2+Num[3]2+...−Length
于是我们现在的任务就是求得当前区间的 N u m [ i ] Num[i] Num[i]即可,莫队搞一搞,注意特判与最后的分数化为最简。
参考代码:
#include <cmath>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define SG string
#define DB double
#define LL long long
using namespace std;
const LL Max=5e4+5;
struct Node{
LL X,Y,Id;
}Ask[Max];
LL N,M,S,Tot=1ll,A[Max],B[Max],Cnt[Max],Ans_X[Max],Ans_Y[Max];
inline LL Read(){
LL X=0;char CH=getchar();bool F=0;
while(CH>'9'||CH<'0'){if(CH=='-')F=1;CH=getchar();}
while(CH>='0'&&CH<='9'){X=(X<<1)+(X<<3)+CH-'0';CH=getchar();}
return F?-X:X;
}
inline void Write(LL X){
if(X<0)X=-X,putchar('-');
if(X>9)Write(X/10);
putchar(X%10+48);
}
bool Cmp(Node P,Node Q){
return B[P.X]==B[Q.X]?P.Y<Q.Y:B[P.X]<B[Q.X];
}
LL GCD(LL X,LL Y){
while(Y^=X^=Y^=X%=Y);
return X;
}
void Insert(LL X){
Tot-=Cnt[X]*Cnt[X];++Cnt[X];Tot+=Cnt[X]*Cnt[X];
}
void Delete(LL X){
Tot-=Cnt[X]*Cnt[X];--Cnt[X];Tot+=Cnt[X]*Cnt[X];
}
int main(){
LL I,J,K;
N=Read(),M=Read();S=sqrt(N);
for(I=1;I<=N;I++){
A[I]=Read();
B[I]=I/S;
}
for(I=1;I<=M;I++){
Ask[I].Id=I;
Ask[I].X=Read();
Ask[I].Y=Read();
}
sort(Ask+1,Ask+1+M,Cmp);
LL Left=1ll,Right=1ll;++Cnt[A[1]];
for(I=1;I<=M;I++){
if(Ask[I].X==Ask[I].Y){
Ans_X[Ask[I].Id]=0;
Ans_Y[Ask[I].Id]=1;continue;
}
while(Right<Ask[I].Y){
Insert(A[++Right]);
}
while(Right>Ask[I].Y){
Delete(A[Right--]);
}
while(Left<Ask[I].X){
Delete(A[Left++]);
}
while(Left>Ask[I].X){
Insert(A[--Left]);
}
LL Length=Ask[I].Y+1-Ask[I].X;
Ans_X[Ask[I].Id]=Tot-Length;
Ans_Y[Ask[I].Id]=Length*(Length-1);
LL _GCD=GCD(Ans_X[Ask[I].Id],Ans_Y[Ask[I].Id]);
Ans_X[Ask[I].Id]/=_GCD;
Ans_Y[Ask[I].Id]/=_GCD;
}
for(I=1;I<=M;I++){
Write(Ans_X[I]),putchar('/'),Write(Ans_Y[I]),putchar('\n');
}
return 0;
}