题意:
给你1-n属于的班级
给你一个[l,r]区间
问你如果要访问这个区间内所有的女生
有多少种走不同教室的方法
思路:
和小z差不多 只不过这个维护的是阶乘
找出来公式之后莫队直接离线处理
莫队更多的是离线排序优化的思想
把所有查询排序处理 然后逐个处理 可以应用到很多方面
1 #include<bits/stdc++.h> 2 #define cl(a,b) memset(a,b,sizeof(a)) 3 #define debug cerr<<#a<<"=="<<a<<endl; 4 using namespace std; 5 typedef long long ll; 6 typedef pair<int,int> pii; 7 8 const int maxn=3e4+10; 9 const int mod=1e9+7; 10 11 int n,m; 12 ll inv[maxn]; 13 ll a[maxn]; 14 ll res[maxn]; 15 ll num[maxn]; 16 17 struct query 18 { 19 int l,r,id,sqr; 20 bool operator < (const query &a) const 21 { 22 if(a.sqr==sqr) return r<a.r; 23 return l<a.l; 24 } 25 } q[maxn]; 26 27 ll quick_mod(ll a,ll x) 28 { 29 ll ans=1; 30 while(x) 31 { 32 if(x&1) 33 { 34 ans=(ans*a)%mod; 35 } 36 a=(a*a)%mod; 37 x>>=1; 38 } 39 return ans; 40 } 41 42 ll getinv(ll x) 43 { 44 return quick_mod(x,mod-2); 45 } 46 47 void init() 48 { 49 for(int i=1; i<=maxn; i++) 50 { 51 inv[i]=getinv(i); 52 } 53 } 54 55 void solve() 56 { 57 int l=1,r=1; 58 ll ans=1; 59 cl(num,0); 60 num[a[1]]++; 61 for(int i=1; i<=m; i++) 62 { 63 while(r<q[i].r) 64 { 65 r++; 66 num[a[r]]++; 67 ans=ans*(r-l+1)%mod*inv[num[a[r]]]%mod; 68 } 69 while(l>q[i].l) 70 { 71 l--; 72 num[a[l]]++; 73 ans=ans*(r-l+1)%mod*inv[num[a[l]]]%mod; 74 } 75 while(r>q[i].r) 76 { 77 ans=ans*num[a[r]]%mod*inv[r-l+1]%mod; 78 num[a[r]]--; 79 r--; 80 } 81 while(l<q[i].l) 82 { 83 ans=ans*num[a[l]]%mod*inv[r-l+1]%mod; 84 num[a[l]]--; 85 l++; 86 } 87 res[q[i].id]=ans; 88 } 89 } 90 91 int main() 92 { 93 int T; 94 scanf("%d",&T); 95 init(); 96 while(T--) 97 { 98 scanf("%d%d",&n,&m); 99 int bk=(int)sqrt(1.0*n); 100 for(int i=1; i<=n; i++) 101 { 102 scanf("%lld",&a[i]); 103 } 104 int l,r; 105 for(int i=1; i<=m; i++) 106 { 107 scanf("%d%d",&l,&r); 108 q[i]= {l,r,i,l/bk}; 109 } 110 sort(q+1,q+m+1); 111 solve(); 112 for(int i=1;i<=m;i++) 113 { 114 printf("%lld\n",res[i]); 115 } 116 } 117 return 0; 118 }/* 119 120 2 121 4 2 122 1 2 1 3 123 1 3 124 1 4 125 1 1 126 1 127 1 1 128 129 */
原文:http://www.cnblogs.com/general10/p/7487314.html