素数迭代
Time Limit : 3000/1000ms (Java/Other) Memory Limit : 65535/32768K (Java/Other)
Total Submission(s) : 9 Accepted Submission(s) : 6
Font: Times New Roman | Verdana | Georgia
Font Size: ← →
Problem Description
定义函数f(i)为i的所有素因子和。
定义g(i)为f(i)的迭代次数,(迭代即f(f(f(...f(i))))),迭代次数至少为1。
当i为素数(即f(i) = i)的时候停止迭代。
现在给定三个数l, r, p,求[l, r]区间内有多少个数x满足g(x) = p;
定义g(i)为f(i)的迭代次数,(迭代即f(f(f(...f(i))))),迭代次数至少为1。
当i为素数(即f(i) = i)的时候停止迭代。
现在给定三个数l, r, p,求[l, r]区间内有多少个数x满足g(x) = p;
Input
多组输入,每组输入三个数,分别代表l, r, p; (2 <= l <= r <= 1000000, 1 <= p <= 1000000)
Output
每组输出一行,根据题意输出一个满足条件的数字;
Sample Input
90 90 3 2 9 1 2 9 2 800 810 4 999999 1000000 2 100000 1000000 1000000
Sample Output
1 4 4 5 2 0 Hint: 对于l = 2, r = 9, p = 2这组数据,根据题意得; f(2) = 2; f(3) = 3; f(4) = 2; f(5) = 5; f(6) = 2+3 = 5; f(7) = 7; f(8) = 2; f(9) = 3; 则迭代次数 g(i) = 2 的有g(4), g(6), g(8), g(9), 共有4个,因此输出4;
Author
感觉这是好题,学到了好几个点。
1.打 素因数和 表 的算法。
如果这个数是素数,这个数的 f(x) 是 1,这个数的倍数的素因数和加上这个数。
/*******打素因数和表*******/
memset(isprime,1,sizeof(isprime));//先把素数标记数组全部初始化为真
for(int i=2; i<=limit; i++){
if(isprime[i]){//如果素数标记为真,那么这是一个素数
for(int j=i+i; j<=limit; j+=i){//遍历给定范围内,这个素数的所有倍数
isprime[j] = 0;//标记为合数
sum[j] += i;//求素因数的和
}
}
}
2.利用 动态数组 vector ,把具有不同特点的元素分别存储。
/*******填 g表 和 m表*******/
for(int i=2; i<=limit; i++){//遍历素因数和表里的每一个元素
if(isprime[i]) g[i] = 1;//素数的m值为1
/****这里g表是从左往右填表的,动态规划的思想****/
else g[i] = g[sum[i]] + 1;//合数的m值为它的素因数和的m值
m[g[i]].push_back(i);//合数i归到它所属的m表下序列中
}
#include<cstdio>
#include<algorithm>
#include<vector>
#include<iostream>
#include<cstring>
using namespace std;
#define limit 1000005
bool isprime [limit+10];
int sum [limit+10], g[limit+10];
vector<int> m [20];
int l, r, p;
void gettable ()
{
/*******打素因数和表*******/
memset(isprime,1,sizeof(isprime));//先把素数标记数组全部初始化为真
for(int i=2; i<=limit; i++){
if(isprime[i]){//如果素数标记为真,那么这是一个素数
for(int j=i+i; j<=limit; j+=i){//遍历给定范围内,这个素数的所有倍数
isprime[j] = 0;//标记为合数
sum[j] += i;//求素因数的和
}
}
}
/*******填 g表 和 m表*******/
for(int i=2; i<=limit; i++){//遍历素因数和表里的每一个元素
if(isprime[i]) g[i] = 1;//素数的m值为1
/****这里g表是从左往右填表的,动态规划的思想****/
else g[i] = g[sum[i]] + 1;//合数的m值为它的素因数和的m值
m[g[i]].push_back(i);//合数i归到它所属的m表下序列中
}
}
int main ()
{
/*******打 素因数和 表, 再打一个g表, 最后还有m表*******/
gettable();
while(~ scanf("%d%d%d", &l, &r, &p) ){
if(p > 12){//大佬通过打表发现,再1 到 1e6 的范围内,p最大为12,大于12的都是不存在的
printf("%d\n",0);
continue;
}
/*******现成的 二分 *******/
int x = lower_bound(m[p].begin(), m[p].end(), l) - m[p].begin();
int y = upper_bound(m[p].begin(), m[p].end(), r) - m[p].begin();
printf("%d\n",y-x);
}
return 0;
}