概率 =
∑
i
=
1
v
(
2
c
n
t
i
)
(
2
l
e
n
)
\frac{\sum_{i=1}^{v}\binom{2}{cnt_i}}{\binom{2}{len}}
(len2)∑i=1v(cnti2)
化简 =
∑
i
=
1
v
c
n
t
i
2
−
l
e
n
l
e
n
(
l
e
n
−
1
)
\frac{\sum_{i=1}^{v}cnt_i^2-len}{len(len-1)}
len(len−1)∑i=1vcnti2−len
莫队维护 \(\ cnt_i^2\) 即可
调试记录
l指针和r指针的更新是相反的
#include<cstdio>#include<cmath>#include<algorithm>#define maxn 50005#define int long longusingnamespace std;struct node{int l, r, id, a, b;}q[maxn];int n, m, a[maxn], cnt[maxn], pos[maxn];intsqr(int x){return x * x;}boolcmp(node a, node b){if(pos[a.l]== pos[b.l])return a.r < b.r;return a.l < b.l;}boolidcmp(node a, node b){return a.id < b.id;}intgcd(int x,int y){if(!y)return x;returngcd(y, x % y);}voidsolve(){int r =0, l =1, ans =0;for(int i =1; i <= m; i++){for(; r < q[i].r; r++) ans -=sqr(cnt[a[r +1]]), cnt[a[r +1]]++, ans +=sqr(cnt[a[r +1]]);for(; r > q[i].r; r--) ans -=sqr(cnt[a[r]]), cnt[a[r]]--, ans +=sqr(cnt[a[r]]);for(; l < q[i].l; l++) ans -=sqr(cnt[a[l]]), cnt[a[l]]--, ans +=sqr(cnt[a[l]]);for(; l > q[i].l; l--) ans -=sqr(cnt[a[l -1]]), cnt[a[l -1]]++, ans +=sqr(cnt[a[l -1]]);if(q[i].l == q[i].r){
q[i].a =0; q[i].b =1;continue;}// printf("%d~%d len = %d ^sum = %d\n", q[i].l, q[i].r, q[i].r - q[i].l + 1, ans);
q[i].a = ans -(q[i].r - q[i].l +1);
q[i].b =(q[i].r - q[i].l +1)*(q[i].r - q[i].l);// printf("a = %d b = %d\n", q[i].a, q[i].b);int tmp =gcd(q[i].a, q[i].b);
q[i].a /= tmp; q[i].b /= tmp;}}signedmain(){scanf("%lld%lld",&n,&m);for(int i =1; i <= n; i++)scanf("%lld",&a[i]);int block =sqrt(m);for(int i =1; i <= m; i++)
pos[i]=(i -1)/ block +1;for(int i =1; i <= m; i++){scanf("%lld%lld",&q[i].l,&q[i].r);
q[i].id = i;}sort(q +1, q + m +1, cmp);solve();sort(q +1, q + m +1, idcmp);for(int i =1; i <= m; i++)printf("%lld/%lld\n", q[i].a, q[i].b);return0;}