題目:題目給出公式,Ni = Ni-1 + NOD(Ni-1),NOD为因子个数,求一个区间[A,B]上有多少个N。
分析:数论,dp,打表。打表计算,查询输出。
首先,打表计算出1000000内的所有素数;
然后,利用素数表,计算1000000内所有数字的因子个数(组合数学,每个因子个数+1相乘);
之后,计算N,然后dp计算区间[0,i]的N个个数S(i);
最后输出S(B)- S(A-1)。
說明:╮(╯▽╰)╭。
#include <cstring>
#include <cstdio>
int visit[1000001];
int prime[1000001];
int divid[1000001];
int N[1000001];
int M[1000001];
int S[1000001];
int main()
{
//打表计算素数
memset(visit, 0, sizeof(visit));
int count = 0;
for (int i = 2; i < 1000001; ++ i)
if (!visit[i]) {
prime[count ++] = i;
for (int j = i+i; j < 1000001; j += i)
visit[j] = 1;
}
//计算因数个数
memset(divid, 0, sizeof(divid));
divid[0] = 0; divid[1] = 1;
for (int i = 2; i < 1000001; ++ i) {
int value = i, ans = 1, move = 0;
while (visit[value] && value > 1) {
int size = 0;
while (value%prime[move] == 0) {
value /= prime[move];
size ++;
}
move ++;
ans *= (size+1);
}
if (value > 1) ans *= 2;
divid[i] = ans;
}
//计算N对应的映射
memset(M, 0, sizeof(M));
M[N[0] = 1] = 1;
for (int i = 1; i < 1000001; ++ i) {
N[i] = N[i-1] + divid[N[i-1]];
if (N[i] > 1000000) break;
M[N[i]] = 1;
}
//计算对应区间[0, i]内N总数
memset(S, 0, sizeof(S));
for (int i = 1; i < 1000001; ++ i)
S[i] = S[i-1] + M[i];
int T, A, B;
while (~scanf("%d",&T))
for (int t = 1; t <= T; ++ t){
scanf("%d%d",&A,&B);
printf("Case %d: %d\n",t,S[B]-S[A-1]);
}
return 0;
}