题目描述
如果一个素数转换成十六进制后是“对称”的,我们将其称为“十六进制对称素数”,例如17(11H)就是一个“十六进制对称素数”,而19(13H)虽然是素数但十六进制并不“对称”。
试统计在[n,m]范围内有多少素数是“十六进制对称素数”。
输入
两个整数n和m
输出
范围内“十六进制对称素数”的个数
思路:使用构造法先构造16进制的数,在进行素性判断即可
#pragma GCC optimize(3)
#pragma comment(linker,"/STACK:102400000,1024000")
#define _CRT_SECURE_NO_WARNINGS
#pragma warning(disable:4996)
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define endl '\n'
#define N 200200
long long int huiwen[N] = { 0 }; //回文数个数小于200000-1
/*构造16进制回文数组*/
void palindrome()
{
for (int j = 0; j <= 15; j++)
{
huiwen[j] = j;
}
long long int newed, x, i; //i作为循环变量
int n = 0;//x在十六进制下是几位数
int count = 0x10;
for (i = 1; i <= 0xffff; i++)
{
newed = 0;
x = i;
n = 0;
do
{
newed = newed * 16 + x % 16; //将x在16进制下倒序
x /= 16;
n++;
} while (x > 0);
huiwen[count++] = pow(16, n) * i + newed; //偶数位(2*n)回文数
if (i <= 0xfff)
for (int k = 0; k <= 15; k++) //注意是15
{
huiwen[count++] = pow(16, n + 1) * i + pow(16, n) * k + newed; //奇数位(2*n+1)回文数
}
}
}
/*判断质数部分*/
/* c 考虑到a * b可能溢出,改为计算 (a * b) % c */
long long mulmod(long long a, long long b, long long mod)
{
long long x = 0, y = a % mod;
while (b > 0)
{
if (b % 2 == 1)
{
x = (x + y) % mod;
}
y = (y * 2) % mod;
b /= 2;
}
return x % mod;
}
/*蒙哥马利算法(模幂运算) */
long long modulo(long long base, long long exponent, long long mod)
{
long long x = 1;
long long y = base;
while (exponent > 0)
{
if (exponent % 2 == 1)
x = (x * y) % mod;
y = (y * y) % mod;
exponent = exponent / 2;
}
return x % mod;
}
/*米勒-拉宾素数检测,不确定算法,迭代次数越多越准确*/
bool Miller(long long p, int iteration)
{
if (p < 2)
{
return false;
}
if (p != 2 && p % 2 == 0)
{
return false;
}
long long s = p - 1;
while (s % 2 == 0)
{
s /= 2;
}
for (int i = 0; i < iteration; i++)
{
long long a = rand() % (p - 1) + 1, temp = s;
long long mod = modulo(a, temp, p);
while (temp != p - 1 && mod != 1 && mod != p - 1)
{
mod = mulmod(mod, mod, p);
temp *= 2;
}
if (mod != p - 1 && temp % 2 == 0)
{
return false;
}
}
return true;
}
bool pri(long long int n)
{
int iteration = 5;//迭代次数
if (Miller(n, iteration))
return true;
else
return false;
}
/*主函数:遍历回文数会超时,使用构造法创造回文数*/
signed main()
{
ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);
long long int i; //i为循环变量
long long int num = 0, n, m; //1 < n < m < 2 ^ 32,num计数用
memset(huiwen, 0, sizeof(huiwen));
palindrome();
cin >> n >> m;
for (i = 1; i < N; i++)
{
if (huiwen[i] <= m && huiwen[i] >= n && pri(huiwen[i]) == true)
{
num++;
}
}
cout << num << endl;
return 0;
}