hdu 5145 NPY and girls 莫队

题意:

给你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 */
时间: 2024-10-20 20:44:45

hdu 5145 NPY and girls 莫队的相关文章

HDU 5145 NPY and girls 莫队算法

对于这类区间查询的问题,如果可以用O(1)的复杂度推到一个曼哈顿距离为1的另外区间的话,就可以直接用莫队算法搞. 从网上搜到的有两种搞法.第一种是先建立曼哈顿距离最小生成树,然后直接dfs遍历整棵树来求解的. 还有一种是先分块,然后把查询按照块的编号为第一关键字,右边界为第二关键字排序,排序直接直接暴力转移. 这样做的复杂度是n * sqrt(n),后面那个sqrt(n)取决于是怎么分块的. 仔细想想感觉这样子搞复杂度差不多就是这样,因为在同一个块中的复杂度怎么搞都是sqrt(n)级别的,就算是

HDU 5145 NPY and girls(莫队算法+乘法逆元)

[题目链接] http://acm.hdu.edu.cn/showproblem.php?pid=5145 [题目大意] 给出一个数列,每次求一个区间数字的非重排列数量.答案对1e9+7取模. [题解] 我们发现每次往里加入一个新的数字或者减去一个新的数字,前后的排列数目是可以通过乘除转移的,所以自然想到用莫队算法处理.因为答案要求取模,所以在用除法的时候要计算逆元. [代码] #include <cstdio> #include <algorithm> #include <

HDU 5145 NPY and girls (莫队分块离线)

题目地址:HDU 5145 莫队真的好神奇..这样的复杂度居然只有n*sqrt(n)... 裸的莫队分块,先离线,然后按左端点分块,按块数作为第一关键字排序,然后按r值作为第二关键字进行排序.都是从小到大,可以证明这样的复杂度只有n*sqrt(n).然后进行块之间的转移. 代码如下: #include <iostream> #include <string.h> #include <math.h> #include <queue> #include <

hdu NPY and girls 莫队+逆元

NPY and girls Time Limit: 8000/4000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Problem Description NPY's girlfriend blew him out!His honey doesn't love him any more!However, he has so many girlfriend candidates.Because there are to

Hdu5145NPY and girls莫队算法

Problem Description NPY's girlfriend blew him out!His honey doesn't love him any more!However, he has so many girlfriend candidates.Because there are too many girls and for the convenience of management, NPY numbered the girls from 1 to n.These girls

【HDU 5145】 NPY and girls(组合+莫队)

pid=5145">[HDU 5145] NPY and girls(组合+莫队) NPY and girls Time Limit: 8000/4000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 593    Accepted Submission(s): 179 Problem Description NPY's girlfriend blew him out!H

HDU 5145 分块 莫队

给定n个数,q个询问[l,r]区间,每次询问该区间的全排列多少种. 数值都是30000规模 首先考虑计算全排列,由于有同种元素存在,相当于每次在len=r-l+1长度的空格随意放入某种元素即$\binom{len}{k_1}$,那么下种元素即为$\binom{len-k_1}{k2}$,以此类推,直至最后直接填满,那么全排列为${\frac{len!}{k_1!k_2!…k_n!}}$ 然后可以发现可以直接O(1)求得左右相邻区间的值(就是乘或除),那么考虑分块莫队. /** @Date : 2

hdu 5381 The sum of gcd 莫队+预处理

The sum of gcd Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) Problem Description You have an array A,the length of A is nLet f(l,r)=∑ri=l∑rj=igcd(ai,ai+1....aj) Input There are multiple test cases. The first line

HDU 4638 Group (莫队算法||线段树离散查询)

题目地址:HDU 4638 先写了一发莫队,莫队可以水过.很简单的莫队,不多说. 代码如下: #include <iostream> #include <string.h> #include <math.h> #include <queue> #include <algorithm> #include <stdlib.h> #include <map> #include <set> #include <s