SPOJ - Horace and his primes(素数+二分查找)

来源:互联网 发布:项尖数据恢复注册码 编辑:程序博客网 时间:2024/05/17 23:11

【题目链接】 点击打开链接

【题意】

              给你一个数列的第一个数,例如90,那么我每次将这个n分解成素数,90 = 2*3^2*5,那么数列的第二个数是2+3+5 = 10;

              那么数列第三个数有 10 = 2*5 ,2+5 = 7,所以数列的第三个数为7

              第三个数7本身为素数了,那么,定义这个数列的order为3。

              问题,给你a,b,k。求 a<= n <=b 中,多少个以n开头的数列的order为k。

【解题方法】

              我们观察一下数据范围,对应于每一个order的数最多1e6。如果order的取值很小的,那么我们就可以开一个vector直接把每一个order对应的数丢进来,然后找答案的时候二分一下。那么我们如何知道这个结论呢?我们可以验证一下,也可以猜一猜,1个1e6范围之内的素数可以拆成多少个数因子之和?从质因数分解的观点来看,也是logn级别的,所以我们这个开一个大小为20的vector就够了,实际上13就够了,之后的K>=13,答案直接就是0了。


【代码君】


////Created by just_sort 2016/12/31//Copyright (c) 2016 just_sort.All Rights Reserved//#include <ext/pb_ds/assoc_container.hpp>#include <ext/pb_ds/tree_policy.hpp>#include <ext/pb_ds/hash_policy.hpp>#include <set>#include <map>#include <queue>#include <stack>#include <cmath>#include <cstdio>#include <cstdlib>#include <cstring>#include <sstream> //isstringstream#include <iostream>#include <algorithm>using namespace std;using namespace __gnu_pbds;typedef long long LL;typedef pair<int, LL> pp;#define REP1(i, a, b) for(int i = a; i < b; i++)#define REP2(i, a, b) for(int i = a; i <= b; i++)#define MP(x, y) make_pair(x,y)const int maxn = 1000010;const int maxm = 2e5;const int maxs = 10;const int INF = 1e9;typedef tree<int,null_type,less<int>,rb_tree_tag,tree_order_statistics_node_update>order_set;//headbool vis[maxn] = {0};int dep[maxn] = {0}, sum[maxn] = {0};vector <int> v[20];void init(){    for(int i = 2; i < maxn; i++){        if(!vis[i]){            for(int j = 2 * i; j < maxn; j += i){                vis[j] = true;                sum[j] += i;            }        }    }    for(int i = 2; i < maxn; i++){        if(!vis[i]){            dep[i] = 1;        }        else{            dep[i] = dep[sum[i]] + 1;        }        v[dep[i]].push_back(i);    }}int main(){    init();//    for(int i  = 0; i < v[10].size(); i++){//        cout << v[10][i] <<" ";//    }    cout<<endl;    int T, a, b, k;    scanf("%d", &T);    while(T--){        scanf("%d%d%d", &a, &b, &k);        if(k >= 13){            printf("0\n");            continue;        }        int l = lower_bound(v[k].begin(), v[k].end(), a) - v[k].begin();        int r = upper_bound(v[k].begin(), v[k].end(), b) - v[k].begin();        //cout << l << " " << r << endl;        cout << r - l << endl;    }    return 0;}


0 0
原创粉丝点击