HDU 5726 (RMQ 二分)
2016-07-20 22:08
337 查看
题目链接:点击这里
题意:每次询问一个区间的gcd,和这个gcd相同的区间的个数。
区间的gcd个数最多不会超过log(max)个, 而且gcd序列又是递减的,所以直接暴力枚举左端点,对右端点二分求出每一个值的区间扔到map里面统计一下就好了。
#include <cstdio> #include <cstring> #include <algorithm> #include <iostream> #include <cmath> #include <map> using namespace std; #define maxn 100005 #define mod 1000000007 int dp[maxn][21]; int a[maxn]; int n, q; map <int, long long> gg; int scan () { char ch=' '; while(ch<'0'||ch>'9')ch=getchar(); int x=0; while(ch<='9'&&ch>='0')x=x*10+ch-'0',ch=getchar(); return x; } void rmq_init () { for (int i = 0; i < n; i++) dp[i][0] = a[i]; for (int j = 1; (1<<j) <= n; j++) { for (int i = 0; i+(1<<j)-1 < n; i++) { dp[i][j] = __gcd (dp[i][j-1], dp[i+(1<<(j-1))][j-1]); } } } int rmq (int l, int r) { int k = 0; while ((1<<(k+1)) <= r-l+1) k++; return __gcd (dp[l][k], dp[r-(1<<k)+1][k]); } void solve () { for (int i = 0; i < n; i++) { int pos = n-1; while (pos >= i) { int tmp = rmq (i, pos); int l = i, r = pos; while (r-l > 1) { int mid = (l+r)>>1; if (rmq (i, mid) == tmp) r = mid; else l = mid; } int cur; if (rmq (i, l) == tmp) cur = l; else cur = r; gg[tmp] += (pos-cur+1); pos = cur-1; } } } int main () { int t, kase = 0; scanf ("%d", &t); while (t--) { printf ("Case #%d:\n", ++kase); gg.clear (); n = scan (); for (int i = 0; i < n; i++) a[i] = scan (); rmq_init (); solve (); q = scan (); while (q--) { int l = scan (), r = scan (); int ans = rmq (l-1, r-1); printf ("%d %lld\n", ans, gg[ans]); } } return 0; }
相关文章推荐
- 观察者模式
- 【jzoj4668】【腐败】【数论】【快速乘】
- 动态规划的思考(三)
- 动态规划的思考(三)
- ubuntu终端下面用startup.sh脚本启动tomcat报错
- 链表中倒数第k个结点
- CSDN修改个人资料的功能,如果内容不符合交互规则,页面没有提示信息
- HTML5的<details>和<summary>
- Struts2 ActionContext 中的数据详解
- 数学书籍下载地址
- 反转链表
- JAVA遍历二叉树
- win10无法使用内置管理员账户打开应用怎么办
- GCD (hdu 5726)
- 深入理解 Objective-C Runtime
- 【2016 Multi-University Training Contest 1】【hdu5723】Abandoned Countries
- time_t tm timeval 和 时间字符串的转换
- (1)下载Spring framework和commons logging jar包
- HTTP请求header信息讲解
- Java 反射 Class对象