本题有几个需要注意的点:
1、需要筛选的素数范围,必须保证字符数组的内容有10^6,所以筛素数时必须要多筛一些
2、前缀和的思想
3、用小数组来实现分离后素数的反转
大体思路:
先用筛法筛出素数存入数组,用二维数组来存储答案,边分离边计算,打表完成后输入数据即可。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define N 3000000//多开点保证筛出的有10^6
int prime[N + 10]={1,1};
char b[1000];
int a[10][N / 3 + 10];
int main()
{
int i,j,k,count;
for(i = 2; i <= N; i++) {//埃式筛法筛素数
if(prime[i]==0) {
for(j = 2; j*i <= N; j++) {
prime[i*j] = 1;
}
}
}
count = 1;
for(i = 2; i <= N; i++) {
if(prime[i]==0) {
int t;
t = i;
j = 0;
memset(b,'\0',sizeof(b));
while (t > 0) {
b[j] = (t % 10) + '0';
t /= 10;
j++;
}
for(k = j - 1; k >= 0; k--) {//因为分离出来的素数是反的,用数组b来实现反转
a[b[k] - '0'][count]++;
count++;
}
/* itoa(i , b , 10);//也可以尝试用下itoa函数,看过去更加简洁
itoa(需要转化的数字, 存入的字符数组, 该数字的进制 );
for(k = 0; k <= strlen(b) - 1 ; k++) {
a[b[k] - '0'][count]++;
count++;
}
*/
if(count > 1000000) //筛了10^6后就退出循环
break;
}
}
for(i = 0; i <= 9; i++) {//前缀和
for(j = 2; j < count; j++) {
a[i][j] += a[i][j-1];
}
}
int T;
scanf("%d", &T);
while (T--) {
int L,R,d;
scanf("%d %d %d", &L, &R, &d);
printf("%d\n", a[d][R] - a[d][L-1]);
}
return 0;
}