补充:戳这里
1、NPY and girls
题意简述:给定一个长度为 (n) 的序列,每次给定一个区间 ([l,r]),求 ((r-l+1)!/(count(1)! imes count(2)! imes ... imes count(n)!))
先预处理出阶乘和阶乘的乘法逆元,然后每次更新除掉原来的数乘上后来的数就好了
(Code Below:)
#include <cstdio>
#include <cctype>
#include <cstring>
#include <cmath>
#include <algorithm>
#define ll long long
using namespace std;
const int maxn=30000+10;
const int p=1e9+7;
int n,m,a[maxn],cnt[maxn],ans[maxn],farc[maxn],inv[maxn],blo,now;
struct Query{
int l,r,id;
}q[maxn];
bool cmp(Query a,Query b){
if((a.l-1)/blo!=(b.l-1)/blo)
return (a.l-1)/blo<(b.l-1)/blo;
return a.r<b.r;
}
inline int read(){
register int x=0,f=1;char ch=getchar();
while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
while(isdigit(ch)){x=(x<<3)+(x<<1)+ch-'0';ch=getchar();}
return (f==1)?x:-x;
}
int fast_pow(int a,int b){
int ret=1;
for(;b;b>>=1,a=(ll)a*a%p)
ret=(ll)ret*(b&1?a:1)%p;
return ret;
}
inline void add(int x){
if(cnt[a[x]]) now=(ll)now*farc[cnt[a[x]]]%p;
now=(ll)now*inv[++cnt[a[x]]]%p;
}
inline void del(int x){
now=(ll)now*farc[cnt[a[x]]--]%p;
if(cnt[a[x]]) now=(ll)now*inv[cnt[a[x]]]%p;
}
int main()
{
farc[1]=1;
for(int i=2;i<=maxn-10;i++) farc[i]=(ll)farc[i-1]*i%p;
inv[maxn-10]=fast_pow(farc[maxn-10],p-2);
for(int i=maxn-11;i>=1;i--) inv[i]=(ll)inv[i+1]*(i+1)%p;
int T=read();
while(T--){
memset(cnt,0,sizeof(cnt));
n=read(),m=read();blo=sqrt(n);
for(int i=1;i<=n;i++) a[i]=read();
for(int i=1;i<=m;i++) q[i].l=read(),q[i].r=read(),q[i].id=i;
sort(q+1,q+m+1,cmp);
int L=1,R=0;now=1;
for(int i=1;i<=m;i++){
while(R<q[i].r) add(++R);
while(R>q[i].r) del(R--);
while(L<q[i].l) del(L++);
while(L>q[i].l) add(--L);
ans[q[i].id]=(ll)farc[q[i].r-q[i].l+1]*now%p;
}
for(int i=1;i<=m;i++) printf("%d
",ans[i]);
}
return 0;
}
2、Lucky
类似一个不简单的询问的处理方式
(Code Below:)
#include <cstdio>
#include <cctype>
#include <cstring>
#include <iostream>
#include <cmath>
#include <algorithm>
#define ll long long
using namespace std;
const int maxn=100000+10;
int n,m,k,a[maxn],b[maxn<<1],c[maxn<<1],tot,blo;ll ans[maxn],now;
struct Query{
int l,r,v,id;
}q[maxn<<2];
bool cmp(Query a,Query b){
if((a.l-1)/blo!=(b.l-1)/blo)
return (a.l-1)/blo<(b.l-1)/blo;
return a.r<b.r;
}
inline int read(){
register int x=0,f=1;char ch=getchar();
while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
while(isdigit(ch)){x=(x<<3)+(x<<1)+ch-'0';ch=getchar();}
return (f==1)?x:-x;
}
inline void addb(int x){now+=(ll)c[k-a[x]];b[a[x]]++;}
inline void delb(int x){now-=(ll)c[k-a[x]];b[a[x]]--;}
inline void addc(int x){now+=(ll)b[k-a[x]];c[a[x]]++;}
inline void delc(int x){now-=(ll)b[k-a[x]];c[a[x]]--;}
inline void add(int l,int r,int v,int id){
q[++tot].l=l;q[tot].r=r;q[tot].v=v;q[tot].id=id;
}
int main()
{
while(cin>>n>>k){
memset(b,0,sizeof(b));
memset(c,0,sizeof(c));
memset(ans,0,sizeof(ans));
tot=now=0;blo=sqrt(n);
for(int i=1;i<=n;i++) a[i]=read();
m=read();
int l1,r1,l2,r2;
for(int i=1;i<=m;i++){
l1=read(),r1=read(),l2=read(),r2=read();
add(r1,r2,1,i);
if(l1>1) add(l1-1,r2,-1,i);
if(l2>1) add(r1,l2-1,-1,i);
if(l1>1&&l2>1) add(l1-1,l2-1,1,i);
}
sort(q+1,q+tot+1,cmp);
int L=0,R=0;
for(int i=1;i<=tot;i++){
while(L<q[i].l) addb(++L);
while(L>q[i].l) delb(L--);
while(R<q[i].r) addc(++R);
while(R>q[i].r) delc(R--);
ans[q[i].id]+=(ll)q[i].v*now;
}
for(int i=1;i<=m;i++) printf("%lld
",ans[i]);
}
return 0;
}