Google code jam Round1B Problem B

本文介绍了一种利用素数筛选与并查集数据结构来解决特定数学问题的方法。通过对指定范围内的整数进行处理,算法可以高效地找出素数及计算互质数对的数量。
 #include <iostream>
#include <fstream>
#include <string>
#include <vector>
#include <map>
#include <assert.h>
#include <boost/pending/disjoint_sets.hpp>
using namespace std;
using namespace boost;
    typedef
      disjoint_sets_with_storage<identity_property_map, identity_property_map,
      find_with_full_path_compression> ds_type;
long long isPrime(long long n)
{
  long long i = 2;

  for (; i * i <= n; i = (i + 1) | 1)
    if (n % i == 0)
      return 0;
  return n > 1;
}
void primeSet(int p, int n, vector < long long >&primeSet, map < int, int >&val_pos)
{
  int i;
  int pos = 0;

  for (i = p; i <= n; i++) {
    if (isPrime(i)) {
      primeSet.push_back(i);
      val_pos[i] = pos++;
    }
  }
}

inline void union_set(int *& arr, int*& rank, int a, int b)
{
  //assert(arr[a] == -1 && arr[b] == -1 && a != b);
  if(rank[a] > rank[b])
      arr[b] = a;
  else
      arr[a] = b;
  if(rank[a] == rank[b])
    rank[b]++;
  //return a;
}
int union_find(int *& arr, int pos)
{
  if(arr[pos] != pos) {
    arr[pos] = union_find(arr, arr[pos]);
  }
  return arr[pos];
}


struct node
{
    int root;    
    int rank;
};

const int poolSize=240000;
node nodePool[poolSize];
    

void makeSet(int cnt)
{
    nodePool[cnt].root=cnt;
    nodePool[cnt].rank = 0;
}

//  recursive findSet
int findSet(int x)    
{
    if(x!=nodePool[x].root)
        nodePool[x].root = findSet(nodePool[x].root);
    
    return nodePool[x].root;
}
int countSet(int size)
{
    int count = 0;
    for(int i = 0; i < size; i++)
        if( nodePool[i].root == i)
            count++;
    return count;
}
void unionSet(int x, int y)
{
    x= findSet(x);
    y= findSet(y);
    if(x==y)  return;  // in the same set
    
    if(nodePool[x].rank > nodePool[x].rank ) {
        nodePool[y].root=x;
    }
    else  {
        nodePool[x].root=y;
        if(nodePool[x].rank==nodePool[y].rank) {
            nodePool[y].rank++;
        }
    }
}




int main(int argc, char **argv)
{
  string line;
  ifstream myfile(argv[1]);
  char outfile[255];

  sprintf(outfile, "%s.out", argv[1]);
  ofstream out(outfile);

  if (myfile.is_open()) {

    getline(myfile, line);
    int cases_count = atoi(line.c_str());

    for (int round_i = 0; round_i < cases_count; round_i++) {
      long long A, B, P;

      myfile >> A >> B >> P;
      getline(myfile, line);

      // compute on customer perfer
      int set_count = 0;
      vector < long long >prm_set;
      map < int, int >val_pos;

      cout << " Processing: P B A " << P << " " << B << " " << A << endl;
      primeSet(P, B - A, prm_set, val_pos);

      int size = prm_set.size();
    
           

      // cout << size << endl;
      // for(int k = 0 ; k < size ; k++)
      // cout << " " << prm_set[k] ; cout << endl;
      //int *sets = (int *)malloc(sizeof(int) * size);

    //for(int i = 0; i < size; i++)
    //    sets[i] = i;
      //memset(sets, 0xFF, sizeof(int) * size);   // set to -1 as parent
      //int *rank = (int *)malloc(sizeof(int) * size);
      //memset(rank, 0, sizeof(int) * size);   // set to -1 as parent */


    //ds_type ds(size);
    for(int i = 0; i < size; i++)
        makeSet(i);


      /* for (long long i = A; i <= B; i++) { int union_before; bool single =
         true; bool need_union = false;
         for(int j = 0; j < size; j++) {
         if(i % prm_set[j] == 0 ){ single = false; break; } } if(single)
         set_count++; } */
      cout << "prime computed" << endl;
      cout << "size:" << size << endl;
      int len = B - A + 1;
      int * status = (int*) malloc(sizeof(int*) * len);
      memset(status, 0, sizeof(int) * len);
      for (int i = 0; i < size; i++) {
      //if( A < prm_set[i])
    //    break;
      long long start;
      if(A % prm_set[i] == 0)
        start = A;
        else
                start = (prm_set[i] - A % prm_set[i]) + A;
      
      for(long long  j = start; j <= B; j = j+prm_set[i]){
        status[j - A] = 1;// 1 means a composite
      }
      }
      for(int i = 0; i < len; i++){
        if(status[i] == 0)
        set_count++;    
    }
cout << "cross finished " << set_count <<  endl;
      for (int i = 0; i < size; i++) {
        //int top1 = i;
    //top1 = union_find(sets, i);
      //int i = 0;
    //if(i < size) {
        // if(sets[i] == -1)
        for (int j = i + 1; j < size; j++) {
          //  int top2 = j;
      //  top2 = union_find(sets, j);
      //  if(top1 == top2)
    //    continue;
          long long pq = prm_set[i] * prm_set[j];
          if (pq > B )
            continue;
          long long left = A % pq;

          if ( left == 0 ||  A - left + pq  < B ) {
              //union_set(sets, rank, top1, top2);
              unionSet(i,j);
      }
        }
      }
     //or (int i = 0; i < size; i++) {
    //cout << sets[i] << " ";
    //cout << rank[i] << " ";
        //if (sets[i] == i)
        //  set_count++;
      //}
    //cout << endl;
      set_count += countSet(size);
      out << "Case #" << round_i + 1 << ": " << set_count << endl;
      cout << "Case #" << round_i + 1 << ": " << set_count << endl;
    }
    myfile.close();
    out.close();
  }
  return 0;
}
请使用c++14 ## 题目描述 Jeff 是伟大的亚特兰蒂斯乐团的一员。乐团中的每位演奏者都已经决定了自己将要演奏的音符(为简化问题,我们假设每位演奏者只演奏一个音符)。我们称两个音符是和谐的,当且仅当其中任意一个音符的频率可以整除另一个音符的频率(这种和谐的定义非常严格,但亚特兰蒂斯人以音乐上的保守著称)。Jeff 知道其他演奏者所演奏的音符之间不一定是和谐的。他希望自己选择的音符能够提升整个交响乐的和谐度,因此他希望选择一个与所有其他演奏者所演奏音符都和谐的音符。 现在,这听起来很简单(因为所有频率都是正整数,Jeff 只需演奏频率为 $1$ 的音符,或者反过来,演奏所有其他音符频率的最小公倍数即可),但不幸的是,Jeff 的乐器只能演奏有限范围内的音符。请帮助 Jeff 判断,是否存在一个音符的频率,使得它与其他所有音符都和谐,并且该频率在 Jeff 乐器可演奏的范围内。 ## 输入格式 输入的第一行是测试用例的数量 $T$。接下来有 $T$ 组测试用例。每组测试用例包含两行。第一行包含三个整数 $N$、$L$ 和 $H$,分别表示其他演奏者的数量、Jeff 乐器可演奏的最低和最高音符频率。第二行包含 $N$ 个整数,表示其他演奏者所演奏音符的频率。 ## 输出格式 对于每个测试用例,输出一行,格式为 “Case #$x$: $y$”,其中 $x$ 是测试用例编号(从 $1$ 开始),$y$ 是 Jeff 可以选择的频率(如果有多个可选频率,输出最小的一个),如果不存在这样的频率,则输出 “NO”。 ## 输入输出样例 #1 ### 输入 #1 ``` 2 3 2 100 3 5 7 4 8 16 1 20 5 2 ``` ### 输出 #1 ``` Case #1: NO Case #2: 10 ``` ## 说明/提示 **数据范围** - $1 \leq T \leq 40$。 **小数据范围(8 分,测试集 1 - 可见)** - $1 \leq N \leq 100$。 - $1 \leq L \leq H \leq 10000$。 - 所有频率不超过 $10000$。 - 时间限制:~~30~~ 3 秒。 **大数据范围(35 分,测试集 2 - 隐藏)** - $1 \leq N \leq 10^4$。 - $1 \leq L \leq H \leq 10^{16}$。 - 所有频率不超过 $10^{16}$。 - 时间限制:~~60~~ 6 秒。
11-14
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值