hdu 5145 莫队算法模板题
来源:互联网 发布:汇编语言 多维数组 编辑:程序博客网 时间:2024/06/05 18:20
题目:
题目分析:
本题是没有修改操作的区间查询,在计算时很容易推出公式,设当前元素个数为N,
那么对于一个区间的方案数就是 n!/ ( sum[a1]! * .......sum[ax]! ) , a1.......ax是选取区间内互不相等的元素
运用到了排列组合的知识,就是所有的元素随机排列,然后排除相同元素内部排列的情况,因为做的运算是乘除法,具有结合性和可逆性,所以可以利用莫队算法进行递推的实现,由于有除法的取模运算,所以要把逆元预处理出来,然后存到数组里o(1)的询问,因为要取模的是一个大质数所以我们可以利用费马小定理求逆元,当然拓展欧几里得也是可以的,具体实现是通过取平方根之后分组进行类似于递推的莫队算法实现,具体算法代码中有详细的注释
代码:
#include <iostream>#include <cstring>#include <algorithm>#include <cstdio>#include <cmath>#define MAX 30009#define MOD 1000000007using namespace std;yalong long inv[MAX];int n , m;int a[MAX];int cnt[MAX];long long output[MAX];//通过费马小定理求取逆元,log的算法,//由费马小定理可知,a对于m的逆元公式= a^(m-2)%m//我们可以利用二进制的性质将线性运算优化为log//也就是将指数化作二进制数,从低到高按照数位进行long long get_inv ( long long x , long long m ){ long long r , y; for ( r = 1 , y = m-2 ; y ; x = x * x %MOD , y >>= 1 ) ( y & 1 ) && ( r = r * x %MOD ); return r;}//预处理,求出所有可能用到的逆元void pre ( ){ inv[0] = 1; for ( int i = 1 ; i < MAX ; i++ ) inv[i] = get_inv ( i , MOD );}//用于分组的,为了保证复杂度是sqrt(n)n,所以选取平方根为分组的界限int Sqrt;//查询数对,先按组别排序,相同组别的按右边界进行排序struct query{ int l,r,id; bool operator < ( const query& a ) const { return ( l/Sqrt < a.l/Sqrt ) || ( l/Sqrt == a.l/Sqrt && r < a.r ); } }q[MAX];void solve ( ){ Sqrt = sqrt ( n * 1.0 ); sort ( q , q + m ); memset ( cnt , 0 , sizeof ( cnt ) ); long long L =1 , R = 1 , tot = 1 , ans = 1; //记录当前点的总数,当前答案的左右边界 cnt[a[1]]++; //因为已经按组别分好,所以左边界的修正范围在sqrt(n)之内,所以在每一位最多的转移是sqrt(n) for ( int i = 0 ; i < m ; i++ ) { //根据乘除法运算的可逆性和结合律,对当前答案进行修正转移,直至当前答案的左右边界与查询对重合, //而提前的分组和排序处理使只有在组别切换时才会出现右边界的回溯,同组进行时只会出现左边界的回走,而每组的长度是sqrt,所以能够达到一定的优化使总的复杂度 //控制在n*sqrt (n)左右 while ( R < q[i].r ) { tot++,R++,cnt[a[R]]++; ans = 1LL * ans * inv[cnt[a[R]]] %MOD; ans = 1LL * ans * tot % MOD; } while ( R > q[i].r ) { ans = 1LL * ans * inv [tot] % MOD; ans = 1LL * ans * cnt[a[R]] % MOD; tot--,cnt[a[R]]--,R--; } while ( L < q[i].l ) { ans = 1LL * ans * inv[tot] % MOD; ans = 1LL * ans * cnt[a[L]] % MOD; tot--,cnt[a[L]]--,L++; } while ( L > q[i].l ) { tot++,L--,cnt[a[L]]++; ans = 1LL * ans * inv[cnt[a[L]]]%MOD; ans = 1LL * ans * tot%MOD; } output[q[i].id] = ans; }}int main ( ){ pre (); int t; scanf ( "%d" , &t ); while ( t-- ) { scanf ( "%d%d" , &n , &m ); for ( int i = 1 ; i <= n ; i ++ ) scanf ( "%d" , &a[i] ); for ( int i = 0 ; i < m ; i ++ ) { scanf ( "%d%d" , &q[i].l , &q[i].r ); q[i].id = i; } solve (); for ( int i = 0 ; i < m ; i++ ) printf ( "%lld\n" , output[i] ); }}
0 0
- hdu 5145 莫队算法模板题
- 最短路+hdu+spfa算法模板题
- 匈牙利算法模板题 hdu 1150
- hdu 1711 KMP算法模板题
- HDU 2063 过山车 匈牙利算法模板题
- 【KM算法 模板】HDU
- 莫队算法模板
- 【模板】莫队算法
- 莫队算法模板
- 莫队算法模板
- 【模板】 莫队算法
- 莫队算法模板
- 莫队算法模板
- HDU 5145 (莫队算法)
- hdu 2255KM算法模板
- hdu 2255(KM算法模板)
- hdu 2544 spfa算法模板
- HDU 1711 KMP算法模板
- 软考信息系统项目管理师考试心得-备考
- 【Tsinsen】A1280. 最长双回文串 【Palindromic Tree】
- spring aop(三)--aop在spring的使用
- XDocument简单入门
- Android 外部存储权限分析
- hdu 5145 莫队算法模板题
- 第十七周项目四—生日差几天 .
- 两个小故事:吞吐量与延迟,信号量与互斥锁
- VIM代码折叠
- cocos2dx 网络编程(CCHttpRequest和CURL两个方式)
- 在Xcode中使用Git进行源码版本控制
- opencv2利用直方图对图像的反投影算法
- python图形处理库Python Imaging Library (PIL)简介及安装
- Microsoft Office 2010组件介绍