【题目链接】 点击打开链接
【题意】
给你一个数列的第一个数,例如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;
//head
bool 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;
}