NPY and girls [莫队+逆元]

传送门

goushijie 巨佬的博客 

#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<iostream>
#define N 30050
#define LL long long 
#define Mod 1000000007
using namespace std;
int a[N],T,n,m,cnt[N],pos[N];
LL s[N],inv[N],ans[N],now,x,y;
struct Node{int l,r,id;}q[N];
void Init(){
	memset(ans,0,sizeof(ans));
	memset(cnt,0,sizeof(cnt));
	memset(pos,0,sizeof(pos)); now=1;
}
void exgcd(int a,int b){
	if(!b){x=1,y=0; return;}
	exgcd(b,a%b); int x1=y , y1=x-a/b*y; x=x1 , y=y1;
}
bool cmp(Node a,Node b){
	if(pos[a.l]==pos[b.l]) return a.r<b.r;
	return pos[a.l]<pos[b.l];
}
void add(int x){
	now = (now * inv[cnt[x]]) % Mod;
	now = (now * s[++cnt[x]]) % Mod;
}
void del(int x){
	now = (now * inv[cnt[x]]) % Mod;
	now = (now * s[--cnt[x]]) % Mod;
}
int main(){
	s[0] = inv[0] = 1;
	for(int i=1;i<=N-50;i++){
		s[i] = (s[i-1] * i) % Mod; 
		exgcd(s[i],Mod);
		inv[i] = (x+Mod) % Mod;
	}
	scanf("%d",&T); while(T--){
		Init(); scanf("%d%d",&n,&m); int siz = sqrt(n);
		for(int i=1;i<=n;i++) scanf("%d",&a[i]),pos[i] = i/siz;
		for(int i=1;i<=m;i++) scanf("%d%d",&q[i].l,&q[i].r),q[i].id=i;
		sort(q+1,q+m+1,cmp); int l=1,r=0; 
		for(int i=1;i<=m;i++){
			while(r<q[i].r) add(a[++r]); while(r>q[i].r) del(a[r--]);
			while(l<q[i].l) del(a[l++]); while(l>q[i].l) add(a[--l]);
			exgcd(now,Mod); x = (x+Mod) % Mod;
			ans[q[i].id] = (s[r-l+1] * x) % Mod;
		}
		for(int i=1;i<=m;i++) printf("%lld\n",ans[i]);
	} return 0;
}

猜你喜欢

转载自blog.csdn.net/sslz_fsy/article/details/85014527