小Z的袜子

题目链接:https://www.luogu.com.cn/problem/P1494

题意:

求在区间[l,r]上取得两个相同颜色的袜子的概率

思路:

莫队,注意开longlong以及最后直接用最大公约数gcd约分

int n,m;
int a[maxn];
int cnt[maxn];
struct node{
	int l,r,id;
}q[maxn];
int k;
bool cmp(node a,node b){
	if(a.l/k!=b.l/k)return a.l/k < b.l/k;
	if((a.l/k)&1)return a.r<b.r;else return a.r>b.r;
}
int res;
int countt=0;
void add(int x){
//	if(!cnt[a[x]])res++;
	cnt[a[x]]++;
	if(cnt[a[x]]==2){
		res+= cnt[a[x]]*(cnt[a[x]]-1);
	}else if(cnt[a[x]]>2){
		res+= (cnt[a[x]]*(cnt[a[x]]-1)-(cnt[a[x]]-1)*(cnt[a[x]]-2));
	}
//	debug(cnt[a[x]]);
}
void del(int x){
	cnt[a[x]]--;
	if(cnt[a[x]]==1)res-=2;
	else if(cnt[a[x]]>=2){
		res-=(cnt[a[x]]+1)*(cnt[a[x]]);
		res+=(cnt[a[x]])*(cnt[a[x]]-1);
	}
//	if(!cnt[x])res--;
}

void solve(){
	cin>>n>>m;
	k=n/sqrt(m*2/3);
	for(int i=1;i<=n;i++)cin>>a[i];
	for(int i=1;i<=m;i++){
		int l,r;cin>>l>>r;
		q[i]=node{l,r,i};
	}
	sort(q+1,q+1+m,cmp);
	vector<pii>ans(m+2);
	for(int i=1,r=0,l=1;i<=m;i++){
		countt=q[i].r-q[i].l+1;
//		debug(countt);
//		debug(q[i].l);
//		debug(q[i].r);
		if(countt==1){
			ans[q[i].id].fi=0;
			ans[q[i].id].se=1;
			continue;
		}
		while(l>q[i].l)add(--l);
		while(l<q[i].l)del(l++);
		while(r<q[i].r)add(++r);
		while(r>q[i].r)del(r--);
		ans[q[i].id].fi=res;
		ans[q[i].id].se=countt;
	}
	
	for(int i=1;i<=m;i++){
//		debug(ans[i].fi);
		if(ans[i].fi==0){
			cout<<ans[i].fi<<'/'<<1<<endl;continue;
		}
		
		int p=ans[i].se*(ans[i].se-1);
		int sk=__gcd(ans[i].fi,p);
		ans[i].fi/=sk;p/=sk;
		
		cout<<ans[i].fi<<'/';
		cout<<p<<endl;
	}
}
posted @ 2025-04-04 19:50  Marinaco  阅读(14)  评论(0)    收藏  举报
//雪花飘落效果