十六进制对称素数

本文探讨如何利用DFS算法统计给定范围内的十六进制对称素数,如11H和13H,通过优化素数判断实现高效计算,揭示在1020范围内存在3个这样的特殊素数。

题目描述

如果一个素数转换成十六进制后是“对称”的,我们将其称为“十六进制对称素数”,例如17(11H)就是一个“十六进制对称素数”,而19(13H)虽然是素数但十六进制并不“对称”。
试统计在[n,m]范围内有多少素数是“十六进制对称素数”。

输入

两个整数n和m

输出

范围内“十六进制对称素数”的个数

样例输入

10 20

样例输出

3

提示

1<n<m<2321<n<m<2^{32}1<n<m<232
样例说明:[10,20]之间的素数有11(BH),13(DH),17(11H),19(13H),其中11,13,17是“十六进制对称素数”


思路

通过dfs不断生成(或者也可以称为搜索)十六进制对称数,并进行判断是否为素数。素数的判断利用了“大于5的质数一定和6的倍数相邻”的性质,相比于朴素试除法节约23\frac{2}{3}32的时间。

AC代码

#include <bits/stdc++.h>

using namespace std;

long long hx[10] = {0, 1, 16, 256, 4096, 65536, 1048576, 16777216, 268435456, 4294967296};
int n, m, res;

bool prime(long long num) {
    if (num == 2 || num == 3) return 1;
    if (num % 6 != 1 && num % 6 != 5) return 0;
    for (int i = 5; i <= floor(sqrt(num)); i += 6)
        if (num % i == 0 || num % (i + 2) == 0) return 0;
    return 1;
}

void dfs(int k, int bit, long long sum) {
    if (k > ceil(bit * 1.0 / 2)) {
        if (sum > m) {
            cout << res;
            exit(0);
        } else if (sum >= n && prime(sum)) ++res;
        return;
    }

    for (int i = k == 1 ? 1 : 0; i <= 15; i++) {
        dfs(k + 1, bit, sum + ((k != bit - k + 1) ? i * hx[k] + i * hx[bit - k + 1] : i * hx[k]));
    }
}

int main() {
    int cnt = 0;
    cin >> n >> m;
    int tmp = n;
    while (tmp) {
        tmp /= 16;
        ++cnt;
    }
    while (cnt) {
        dfs(1, cnt, 0);
        ++cnt;
    }
    return 0;
}
实验二 非对称加密算法实验 一、实验目的 1、理解非对称密码的基本思想 2、理解 RSA算法的原理 3、掌握RSA算法的加解密过程和实现方法 二、实验要求 1、实验前学生应具备以下知识: (1)了解非对称加密技术基本概念; (2)了解几种非对称加密算法的原理; (3)掌握非对称加密技术的特点和应用场景。 2、实验内容可根据实验室的具体情况和课时安排的变化进行适当的调整实验过程中,部分实验内容需要与相邻的同学配合完成。此外,学生需要将实验的结果记录下来,实验内容中的思考题以书面形式解答并附在实验报告的后面。 3、需要注意的是,学生在实验过程中要严格按实验指导书的操作步骤和要求操作,且小组成员应紧密配合,以保证实验过程能够顺利完成。 三、实验环境 Windows, C++ 四、实验内容 1、理解并实现RSA密码加解密流程 2、手工计算 RSA 密钥并检验,将其应用于签名中并验证 3、动手编写RSA算法代码 4、调试验证RSA算法程序的可用性 五、实验步骤 1、设计程序流程 (1)加解密计算 非对称密钥算法的加解密需要有两把钥匙——公钥和私钥,公钥用来加密,私钥用来解密,公钥e可以自己选定,但需要满足gcd(e, φ(n))=1的条件,私钥d需要通过参数生成,这里所需要的参数包括素数p、q和公钥e,通过公式de=1mod(φ(n))计算得到。 (2)加密过程 1)加密过程首先需要用户输入明文; 2)输入的明文是字符串格式,需要做格式转换变成数值,用于后续加密计算; 3)加密,将明文数值作加密处理; 4)得到明文数值的加密数值后,需要对加密数值做格式化处理,然后输出。 (3)解密过程 1)解密过程首先需要用户输入明文; 2)输入的密文是字符串格式,需要做格式转换变成数值,用于后续解密计算; 3)解密,将密文数值作解密处理; 4)得到密文数值的解密数值后,需要对解密数值做格式化处理,然后输出。 2、构建代码模块 3、搭建代码框架 Int main() { /* 定义大素数p,q,公钥e,私钥d,模数n,与模数n的互素元素个数fai_n */ int p, q, e, d, n, fai_n; // 1. 提示用户输入参数 // 2. 随后计算出私钥d // 3. 计算出模数n,计算n所占的字节数n_length,后续将根据n_length对明文分组 /* 提示用户输入明文字符,将明文存入数组plain_arr中 */ /* 明文格式转换,通过plain_format函数实现 */ // 1. 对明文进行分组,因为明文数据大小不能超过模数n,因此明文每个分组所占字节数应比n_length小,这里设置明文分组所占字节为n_length-1比较保险,不容易出错。 // 2. 将明文的每个分组的字符串数据格式化成数值形式。 /* 明文加密 */ // 1. 将明文分组后的数值形式通过公钥e进行加密,得到密文数值。 // 2. 将密文数值信息存入密文数值数组cipher_data_arr中。 /* 加密后密文的格式化输出,直接将数值以十六进制形式输出,每组密文的占位数必须相等,以便解密时能正确分组,这里通过print_cipher_text函数来实现 */ /* 提示用户输入密文字符,将明文存入数组cipher_arr中 */ /* 密文格式转换,通过cipher_format函数实现 */ // 1. 对密文进行分组,因为密文数据大小不能超过模数n,但是最大可能是n-1,所以密文的字节长度最大需要n_length个字节。 // 2. 将密文(十六进制字符串)对应的n_length个字节转化成数值形式。 /* 密文解密 */ // 1. 将密文分组后的数值形式通过私钥d进行解密,得到明文数值。 // 2. 将明文数值信息存入明文数值数组plain_data_arr中 /* 解密后明文的格式化输出,这里的转化稍微复杂一些,这里通过print_cipher_text函数来实现 */ } 4、实现代码逻辑 (1)int cmp_n_space(int n); // 计算模数n所占的字节数 (2)void plain_format(char *plain_arr, long long *plain_data_arr, int n_length); // 将plain_arr中的字符串按n_length-1的字节长度转换成long long型放入plain_data_arr中 (3)long long rsa_encrypt(long long cipher_data, int n_length, int e, int n); // 加密函数:将plain_data加密成cipher_data,然后返回 (4)void print_cipher_text(long long *cipher_data_arr, int n_length); // 加密后密文打印函数 (5)void cipher_format(char *cipher_arr, long long *cipher_data_arr, int n_length); // 将密文中的字符串按n_length的字节长度转换成long long型放入cipher_data_arr数组中 (6)long long rsa_decrypt(long long plain_data, int n_length, int d, int n); // 解密函数:将cipher_data解密成plain_data,然后返回 (7)void print_plain_text(long long *plain_data_arr); // 解密后明文打印函数 六、示例代码
最新发布
10-30
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值