zoukankan      html  css  js  c++  java
  • CGCDSSQ Codeforces 475D

    思路:将数据存入gcd二维数组的第0列,第j列的gcd值是第j-1列的i行和i+2的j次方的最大公约数,

    gcd[i][j] = Gcd(gcd[i][j - 1], gcd[i + bin[j - 1]][j - 1]);

    将gcd数组计算好后,进行询问query,由于系统的Log2太慢,所以编写了Log数组直接使用。
    int k = Log[r - l + 1];
    return Gcd(gcd[l][k], gcd[r - bin[k] + 1][k]);
    二分查找bi函数:将左端固定值为x,寻找值仍为x的右端,并返回;遍历完成即统计完成。
     1 #include<iostream>
     2 #include <cstdio>
     3 #include <cstring>
     4 #include<algorithm>
     5 #include<map>
     6 #define maxn 100010
     7 using namespace std;
     8 typedef long long LL;
     9 int gcd[maxn][32], n, Log[maxn], bin[32];
    10 map<int, LL> mp;
    11 int Gcd(int a, int b) {
    12     return b ? Gcd(b, a % b) : a;
    13 }
    14 void rmqInit() {
    15     Log[0] = -1; bin[0] = 1;
    16     for (int i = 1; i < 20; ++i) {
    17         bin[i] = bin[i - 1] << 1;//1 2 4 8 16 32
    18     }
    19     for (int i = 1; i <= n; ++i) {
    20         Log[i] = Log[i >> 1] + 1;//-1 0 1 1 2 2 2 2 3 3 3 3 3 3 3 3 
    21     }
    22     for (int j = 1; bin[j] <= n; ++j) {
    23         for (int i = 1; i + bin[j - 1] - 1 <= n; ++i) {
    24             gcd[i][j] = Gcd(gcd[i][j - 1], gcd[i + bin[j - 1]][j - 1]);
    25         }
    26     }
    27 }
    28 int query(int l, int r) {//询问区间为l,r的gcd值
    29     int k = Log[r - l + 1];//
    30     return Gcd(gcd[l][k], gcd[r - bin[k] + 1][k]);//bin[k]就是2的k次方
    31 }
    32 int bi(int i, int l, int r, int x) {  //x是i到l的最大公约数
    33     while (r - l > 1) {  //右区间-左区间等于1时停止
    34         int mid = l + r >> 1;  
    35         int val = query(i, mid);
    36         if (val >= x) l = mid;   
    37         else r = mid - 1; 
    38     }
    39     //找出最大公约数是x的右区间
    40     return query(i, r) == x ? r : l;
    41 }
    42 int main() {
    43     scanf_s("%d", &n);
    44     for (int i = 1; i <= n; ++i) {
    45         cin >> gcd[i][0];
    46     }
    47     rmqInit();
    48     for (int i = 1; i <= n; ++i) {
    49         int l = i;    //左区间从1到n,一行一行搜索
    50         while (true) {
    51             if (l == n + 1) break;  //左区间超过n则跳出
    52             int val = query(i, l);   //询问区间为i,l的gcd值
    53             int r = bi(i, l, n, val); 
    54             mp[val] += r - l + 1;
    55             l = r + 1;
    56         }
    57     }
    58     int q, x;
    59     scanf_s("%d", &q);
    60     while (q--) {
    61         scanf_s("%d", &x);
    62         printf("%I64d
    ", mp[x]);
    63     }
    64     return 0; 
    65 }
  • 相关阅读:
    shell 测试命令
    shell 键盘录入和运算
    shell 的变量
    shell 脚本 helloworld
    让windows系统的DOS窗口也可以显示utf8字符集
    wxpython发布还自己图标的程序
    弥补wxpython无背景图片缺陷
    wxPython实现在浏览器中打开链接
    使用py2exe发布windows平台Python
    python os模块实用函数
  • 原文地址:https://www.cnblogs.com/0211ji/p/13184751.html
Copyright © 2011-2022 走看看