zoukankan      html  css  js  c++  java
  • 数学 之 Codeforces 359D

    //  [7/13/2014 Sjm]
    /*
    直接暴力,超时。。
    不过有一点大家都知道:
    如果 (b%a == 0),(c%b == 0), 那么 (c%a == 0) 一定是成立的。
    故而在以一个数字a为中心,向两边寻找能够被a整除的数后,已被寻找到的的数是不用再计算的。。。
    (因为即使计算这些已被寻找到的数,边界r、l也一定会 小于或等于 以数字a为中心所得到的边界r、l。)大哭,,,比赛时怎么就没想到呢。。。。
    */
     1 #include <iostream>
     2 #include <cstdlib>
     3 #include <cstdio>
     4 #include <algorithm>
     5 using namespace std;
     6 const int MAX = 300005;
     7 
     8 int arr[MAX], arr_L[MAX];
     9 int n;
    10 
    11 void Solve(){
    12     int cnt = 0, dis = -1;
    13     int l, r;
    14     for (int i = 0; i < n;) {
    15         l = r = i;
    16         while (l && !(arr[l - 1] % arr[i])) { --l; }
    17         while (r < (n - 1) && !(arr[r + 1] % arr[i])) { ++r; }
    18         i = r + 1;
    19         int t_dis = r - l;
    20         if (t_dis > dis) {
    21             cnt = 0;
    22             dis = t_dis;
    23         }
    24         if (t_dis == dis) {
    25             arr_L[cnt++] = l + 1;
    26         }
    27     }
    28     printf("%d %d
    ", cnt, dis);
    29     for (int i = 0; i < cnt; i++) {
    30         printf("%d ", arr_L[i]);
    31     }
    32 }
    33 
    34 int main()
    35 {
    36     scanf("%d", &n);
    37     for (int i = 0; i < n; ++i) {
    38         scanf("%d", &arr[i]);
    39     }
    40     Solve();
    41     return  0;
    42 }
    //  [7/11/2014 Sjm]
    /*这是另外一种做法:虽然有些麻烦,但收获很多(Sparce Table算法,以及又一次二分(话说对二分有阴影))
    知识点:math + Sparce Table算法(DP) + 二分
    math:
      数组中[l, r]区间中任意一个数都能被aj整除,则aj必然满足aj是[l,r]中最小的。。
      即: 对于区间[l, r], min(l, r) = gcd(l, r)
    Sparce Table算法(DP):
      为了在O(1)的时间,获取某区间的min以及gcd,采用Sparce Table算法。
      Sparce Table算法:(本质就是DP)

        预处理:

            状态:dp[i][j] := 区间[i, i+2^j-1]的函数F值

            决策:dp[i][j] = F(dp[i][j-1],  dp[i+2^(j-1)][j-1])

            (此题中 函数F 即:min(), gcd())

        查询:

            设查询到区间为 [m, n],区间总共有 (n-m+1) 个数

            据方程 2^k <= (n-m+1) 求解出 k,

            可得:dp[m][n] = F(dp[m][k], dp[n-2^k+1][k])

                    (表达式数中有重叠,但保证了结果的正确性)

    二分:
      采用二分的方法,寻找出满足条件的 (r-l) 的最大值*/
      1 #include <iostream>
      2 #include <cstdlib>
      3 #include <cstdio>
      4 #include <cstring>
      5 #include <cmath>
      6 #include <algorithm>
      7 #include <vector>
      8 using namespace std;
      9 const int MAX_num = 300005;
     10 const int MAX_pow = 20;
     11 const int INF = 0x3f3f3f3f;
     12 
     13 int T, n;
     14 
     15 int arr_min[MAX_num][MAX_pow];
     16 int arr_gcd[MAX_num][MAX_pow];
     17 
     18 int Gcd(int a, int b) {
     19     if (0 == b) { return a; }
     20     else return Gcd(b, a%b);
     21 }
     22 
     23 void ST() {
     24     int MAX_j = (int)(log2((double)(n))) + 1;
     25     for (int j = 1; j < MAX_j; ++j) {
     26         for (int i = 0; i < n; ++i) {
     27             int tep = 1 << (j - 1);
     28             if (i + tep < n) {
     29                 arr_min[i][j] = min(arr_min[i][j - 1], arr_min[i + tep][j - 1]);
     30                 arr_gcd[i][j] = Gcd(arr_gcd[i][j - 1], arr_gcd[i + tep][j - 1]);
     31             }
     32         }
     33     }
     34 }
     35 
     36 bool Judge(int len) {
     37     int tep = (int)(log2((double)(len + 1)));
     38     for (int i = 0; i < n - len; i++) {
     39         int j = i + len;
     40         int t_min = min(arr_min[i][tep], arr_min[j - (1 << tep) + 1][tep]);
     41         int t_gcd = Gcd(arr_gcd[i][tep], arr_gcd[j - (1 << tep) + 1][tep]);
     42         if (t_gcd == t_min) {
     43             return true;
     44         }
     45     }
     46     return false;
     47 }
     48 
     49 int Binary_search() {
     50     int l = 0, r = n - 1;
     51     int mid;
     52     while (l < r) {
     53         mid = l + ((r - l + 1) >> 1);
     54         //cout << "l = " << l << endl;
     55         if (Judge(mid)) { l = mid; }
     56         else { r = mid - 1; }
     57     }
     58     //cout << "l = " << l << endl;
     59     return l;
     60 }
     61 
     62 
     63 void myOutput(int len) {
     64     vector<int> vec;
     65     int tep = (int)(log2((double)(len + 1)));
     66     if (len > 0) {
     67         for (int i = 0; i < n - len; i++) {
     68             int j = i + len;
     69             int t_min = min(arr_min[i][tep], arr_min[j - (1 << tep) + 1][tep]);
     70             int t_gcd = Gcd(arr_gcd[i][tep], arr_gcd[j - (1 << tep) + 1][tep]);
     71             if (t_gcd == t_min) {
     72                 vec.push_back(i);
     73             }
     74         }
     75     }
     76     else {
     77         for (int i = 0; i < n; ++i) {
     78             vec.push_back(i);
     79         }
     80     }
     81     printf("%d %d
    ", vec.size(), (len > 0) ? len : 0);
     82     for (int i = 0; i < vec.size(); ++i) {
     83         printf("%d ", vec[i] + 1);
     84     }
     85     printf("
    ");
     86 }
     87 
     88 int main()
     89 {
     90     //freopen("input.txt", "r", stdin);
     91     memset(arr_min, INF, sizeof(arr_min));
     92     memset(arr_gcd, INF, sizeof(arr_gcd));
     93     scanf("%d", &n);
     94     for (int i = 0; i < n; ++i) {
     95         scanf("%d", &arr_min[i][0]);
     96         arr_gcd[i][0] = arr_min[i][0];
     97     }
     98     ST();
     99     myOutput(Binary_search());
    100     return 0;
    101 }
  • 相关阅读:
    iptables学习笔记
    启动级别和单用户模式
    Apache虚拟主机配置模板
    LAMP环境搭建问题
    LAMP环境搭建
    C++面向对象高级编程(九)Reference与重载operator new和operator delete
    C++面向对象高级编程(八)模板
    C++面向对象高级编程(七)point-like classes和function-like classes
    C++面向对象高级编程(六)转换函数与non-explicit one argument ctor
    C++面向对象高级编程(五)类与类之间的关系
  • 原文地址:https://www.cnblogs.com/shijianming/p/4140832.html
Copyright © 2011-2022 走看看