1133: 加密时间限制: 1 Sec 内存限制: 128 MB

本文解析了一种加密方法,通过实例演示如何将给定的加密密文如 'zww' 转换回原始字符串 'zw'。解题思路涉及字符计数,介绍了一种高效处理加密字符串的方法,避免了直接查找不同字符的复杂性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目描述

加密在计算机领域是不可或缺的一部分,现在有如下一种加密方法:
设字符串s = c1c2…cm(1≤m≤10)c1...cm均为小写英文字母。
字符串s加密后变为c1c2c2c3c3c3.....
例如,如果s =“ abs”,则加密后s =“abbsss”。
现在给定一些加密后的字符串,请你将其解密。

 

输入

第一行输入一个整数T(0<T<10);而后有T组测试样例,
每组测试样例第一行包含一个整数n(1≤n≤55)表示密文字符串的长度。第二行为加密的密文。 它仅包含小写英文字母。且长度为n。
题目包证存在答案。

 

输出

对于每组测试样例,打印其加密前的字符串。
 

样例输入 Copy

2
1
z
3
zww

样例输出 Copy

z
zw

解题思路:题目还是很简单的,一开始我考虑的时候没有注意他的字母可以相同,就按照找不同的字母来做了,但是题目中有个点,他这个加密的玩意可能原码都是相同的字符,这里就必须按照计数做了,不能在偷巧了,这里计数有俩种办法吧(可能还有很多),在输入的时候就按照计数的方式构成字符串然后输出,我感觉这种更好(更快),另外就是按照我的这种整个读取之后再处理,我是在使用string读取之后,为了更方便就按照读取之后处理了。 

//字符串解密
//密文只包含小写字母,且长度为n,题目保证存在答案(这点很重要,防止数据溢出)
//这个应该就是找不同吧,不对,还有个点万一都是相同字符这种想法就不行了
//还得计数
#include<iostream>
#include<string>
using namespace std;

int main()
{
	int number = 0;
	cin >> number;
	for (int i = 0; i < number; ++i)
	{
		int middle;
		cin >> middle;
		string arr;//处理初始化这个事
		string end;
		cin >> arr;
		int flag = 1;
		int step = 0;
		for (int j = 0; j < arr.size(); ++j)
		{
			if (++step == flag)
			{
				end.push_back(arr[j]);
				step = 0;
				flag++;
				continue;
			}
		}
		cout << end << endl;
	}
	return 0;
}

 

<think>好的,我需要帮助用户编写一个关于RSA加密算法的实验流程代码,要求使用Dev C++编写,并且需要输入素数p和q、公钥、明文,最后输出内存占用、CPU占用,以及时间和空间复杂度。让我仔细思考如何一步步实现这个需求。 首先,RSA算法的基本步骤是密钥生成、加密和解密。用户需要输入两个素数p和q,然后计算n=p*q,欧拉函数φ(n)=(p-1)*(q-1)。接下来选择公钥e,要求e与φ(n)互质,通常选65537。然后计算私钥d,满足d*e ≡ 1 mod φ(n),这需要扩展欧几里得算法。不过用户要求输入公钥,所以可能不需要生成e,而是让用户输入e,但需要验证e是否与φ(n)互质。不过用户可能更希望程序自动生成密钥对,但根据用户的问题描述,可能用户需要输入公钥e,所以需要处理这个部分。 接下来,用户要输入明文,可能是一个整数者字符串。如果是字符串,需要转换成整数进行处理。但RSA通常处理的是数字,所以可能需要将字符转换为ASCII码,者分块处理,但为了简化,可能直接让用户输入一个整数作为明文。 然后,代码执行完后需要输出内存占用量(兆)、CPU占用(兆),以及时间和空间复杂度。这部分需要注意如何在C++中测量内存和CPU使用情况。不过,C++标准库中没有直接获取内存和CPU占用的函数,可能需要使用操作系统特定的API。例如,在Windows下可以使用GetProcessMemoryInfo来获取内存使用情况,而CPU占用可能需要更复杂的方法,者使用第三方库。不过这可能对用户来说比较复杂,特别是对于学生实验来说,可能难以实现。用户可能希望得到近似值,者使用伪数据。需要确认这一点,但根据问题描述,用户可能希望实际测量这些指标,所以需要找到在Dev C++(通常是Windows环境)中实现的方法。 另外,时间复杂度和空间复杂度是理论分析,不需要在代码中动态计算,而是在最后输出理论值。例如,RSA的时间复杂度主要取决于模幂运算,使用快速幂算法的话是O(log exponent),而空间复杂度主要与存储大数相关,可能为O(1)取决于数字的大小。 现在,考虑代码的结构: 1. 输入p和q,并进行素数检查。需要实现一个判断素数的函数,但为了简化,可能假设用户输入的是正确素数,者进行简单的素数检测,比如试除法。但试除法对于大数效率不高,不过作为实验代码,可以接受。 2. 输入公钥e,需要检查e是否与φ(n)互质。即gcd(e, φ(n)) == 1。这里需要计算φ(n) = (p-1)*(q-1),然后求e和φ(n)的最大公约数。 3. 计算私钥d,即e的模反元素,使用扩展欧几里得算法。 4. 输入明文m,然后加密为c = m^e mod n。 5. 解密c得到m' = c^d mod n,验证是否正确。 6. 输出内存和CPU占用,以及时间和空间复杂度分析。 关于内存和CPU的测量: 在Windows下,可以使用Windows API函数,比如GetProcessMemoryInfo来获取当前进程的内存使用情况。例如,PROCESS_MEMORY_COUNTERS结构中的WorkingSetSize表示当前使用的物理内存量。将其除以1024*1024得到兆字节。对于CPU使用率,可能需要更复杂的方法,比如使用GetProcessTimes函数计算进程的内核和用户时间,但实时显示可能困难。不过,用户可能只需要在程序结束时输出CPU使用量,这可能需要其他方法,者只能输出程序运行的时间而非CPU占用。这可能需要进一步确认,但根据问题描述,用户希望输出CPU占用量,可能需要使用其他方法,者可能用户误以为可以简单获取,因此可能需要用近似值注释说明无法直接获取。 可能用户对CPU占用的理解是程序运行的时间,所以可以用clock()函数计算程序执行的时间,然后输出。但实际CPU占用率(如任务管理器中的百分比)可能难以获取。因此,可能需要澄清,但按照用户的要求,可能需要输出时间消耗,比如执行时间,以及内存占用。 现在,整合这些思路,编写代码的大纲: - 包含必要的头文件,如iostream, cmath, windows.h(用于内存信息), time.h(用于时间测量)。 - 函数:判断素数(可选,如果要做输入检查)。 - 函数:计算gcd(用于检查e和φ(n)是否互质)。 - 函数:扩展欧几里得算法求模反元素d。 - 主函数: 1. 输入p和q,检查是否为素数(可选)。 2. 计算n和φ(n)。 3. 输入公钥e,检查是否满足gcd(e, φ(n)) == 1,若不满足则报错。 4. 计算私钥d。 5. 输入明文m(整数)。 6. 加密c = mod_pow(m, e, n)。 7. 解密m_decrypted = mod_pow(c, d, n)。 8. 输出加密和解密结果。 9. 输出内存占用,CPU时间时间复杂度分析。 关于模幂运算,需要实现快速幂算法,因为直接计算大指数会非常慢,且容易溢出。使用快速幂并取模,同时处理大数。但由于C++的int类型有限,可能需要使用long long者大数库,但作为实验代码,可能假设输入的数较小,使用long long类型。 接下来,处理内存占用的测量。使用GetProcessMemoryInfo函数需要包含psapi.h,并链接psapi.lib。在Dev C++中,可能需要在编译器选项中添加-lpsapi。例如: #include <windows.h> #include <psapi.h> 然后,在代码中调用: PROCESS_MEMORY_COUNTERS pmc; if (GetProcessMemoryInfo(GetCurrentProcess(), &pmc, sizeof(pmc))) { SIZE_T physMemUsed = pmc.WorkingSetSize; // 转换为MB double mbUsed = physMemUsed / (1024.0 * 1024.0); cout << "内存占用: " << mbUsed << " MB" << endl; } 对于时间测量,可以使用clock()函数: clock_t start = clock(); // 执行代码 clock_t end = clock(); double time_taken = double(end - start) / CLOCKS_PER_SEC; 但这里的时间是CPU时间,可能用户需要的是实际经过的时间,可以使用<chrono>库: #include <chrono> using namespace std::chrono; auto start = high_resolution_clock::now(); // 代码 auto end = high_resolution_clock::now(); auto duration = duration_cast<milliseconds>(end - start); cout << "时间: " << duration.count() << " 毫秒" << endl; 但可能用户希望输出的是时间复杂度的大O表示,而不是实际时间。问题描述中的要求是“输出时间复杂度和空间复杂度”,所以需要理论分析,而不是实际测量的运行时间。这需要用户明确,但根据问题描述,用户可能希望代码执行完后输出理论上的复杂度,比如O(log exponent)等,而不是实际时间。但问题中又提到“输出内存占多少兆 cpu占多少兆”,这里的“cpu占”可能是指CPU使用量,比如占用了多少CPU时间百分比,但通常来说,程序运行时的CPU占用率很难在程序内部获取,可能需要外部工具。因此,可能用户存在误解,需要澄清,但根据要求,可能需要输出理论上的复杂度,同时输出实际的内存使用量(通过API获取)和可能的执行时间。 现在,综合这些因素,编写代码的步骤: 1. 输入p和q,这里假设用户输入的是素数,不进行验证,者添加简单的素数检查。 2. 计算n = p*q,phi = (p-1)*(q-1)。 3. 输入公钥e,检查gcd(e, phi)是否为1,否则提示错误。 4. 计算d,即e的模逆元,使用扩展欧几里得算法。 5. 输入明文m(整数)。 6. 加密:c = mod_pow(m, e, n)。 7. 解密:m_decrypted = mod_pow(c, d, n)。 8. 输出加密后的密文和解密后的明文。 9. 测量并输出内存占用,程序运行时间,以及输出时间复杂度和空间复杂度的分析。 现在,处理各个函数: - 快速幂取模函数: long long mod_pow(long long base, long long exponent, long long mod) { long long result = 1; base = base % mod; while (exponent > 0) { if (exponent % 2 == 1) { result = (result * base) % mod; } exponent = exponent >> 1; base = (base * base) % mod; } return result; } - 扩展欧几里得算法求逆元: long long extended_gcd(long long a, long long b, long long &x, long long &y) { if (b == 0) { x = 1; y = 0; return a; } long long gcd = extended_gcd(b, a % b, x, y); long long temp = x; x = y; y = temp - (a / b) * y; return gcd; } long long mod_inverse(long long a, long long m) { long long x, y; long long gcd = extended_gcd(a, m, x, y); if (gcd != 1) { return -1; // 逆元不存在 } else { return (x % m + m) % m; } } 现在,将这些整合到主函数中,并添加内存时间的测量。 关于内存占用的测量,需要注意在代码中何时获取内存信息,可能在程序结束前获取。此外,可能需要处理大数的问题,例如使用long long可能会溢出,当p和q较大时,n可能超过long long的范围(例如,如果p和q都是较大的素数,比如超过3e9,那么n会是1e19,超过long long的9e18)。因此,可能需要使用更大的数据类型,比如unsigned long long,者使用大数库,但作为实验代码,可能假设输入的数较小。 此外,用户可能希望输入的是字符串明文,但RSA通常加密的是数字,所以可能需要将字符串转换为数字。例如,将每个字符的ASCII码拼接起来,但这样可能超过数据类型的范围。因此,在实验代码中,可能限制用户输入一个整数作为明文。 现在,编写完整的代码: #include <iostream> #include <windows.h> #include <psapi.h> #include <chrono> #include <cmath> using namespace std; using namespace std::chrono; // 快速幂取模 long long mod_pow(long long base, long long exponent, long long mod) { long long result = 1; base = base % mod; while (exponent > 0) { if (exponent % 2 == 1) { result = (result * base) % mod; } exponent = exponent >> 1; base = (base * base) % mod; } return result; } // 扩展欧几里得求逆元 long long extended_gcd(long long a, long long b, long long &x, long long &y) { if (b == 0) { x = 1; y = 0; return a; } long long gcd = extended_gcd(b, a % b, x, y); long long temp = x; x = y; y = temp - (a / b) * y; return gcd; } long long mod_inverse(long long a, long long m) { long long x, y; long long gcd = extended_gcd(a, m, x, y); if (gcd != 1) { return -1; // 逆元不存在 } else { return (x % m + m) % m; } } // 判断素数(简单版本) bool is_prime(int num) { if (num <= 1) return false; if (num <= 3) return true; if (num % 2 == 0 || num % 3 == 0) return false; for (int i = 5; i*i <= num; i += 6) { if (num % i == 0 || num % (i+2) == 0) return false; } return true; } int main() { // 记录开始时间内存 auto start_time = high_resolution_clock::now(); PROCESS_MEMORY_COUNTERS pmc_start, pmc_end; GetProcessMemoryInfo(GetCurrentProcess(), &pmc_start, sizeof(pmc_start)); long long p, q; cout << "请输入素数p和q: "; cin >> p >> q; if (!is_prime(p) || !is_prime(q)) { cout << "pq不是素数,请重新输入!" << endl; return 1; } long long n = p * q; long long phi = (p - 1) * (q - 1); long long e; cout << "请输入公钥e: "; cin >> e; // 检查e是否与phi互质 long long x, y; long long gcd = extended_gcd(e, phi, x, y); if (gcd != 1) { cout << "e与φ(n)不互质,请重新选择e!" << endl; return 1; } long long d = mod_inverse(e, phi); if (d == -1) { cout << "无法计算私钥d,请检查输入!" << endl; return 1; } long long m; cout << "请输入明文(整数): "; cin >> m; // 加密 long long c = mod_pow(m, e, n); // 解密 long long m_decrypted = mod_pow(c, d, n); cout << "加密后的密文: " << c << endl; cout << "解密后的明文: " << m_decrypted << endl; // 获取结束时间内存 auto end_time = high_resolution_clock::now(); GetProcessMemoryInfo(GetCurrentProcess(), &pmc_end, sizeof(pmc_end)); // 计算内存占用 SIZE_T mem_used = pmc_end.WorkingSetSize - pmc_start.WorkingSetSize; double mem_used_mb = mem_used / (1024.0 * 1024.0); // 计算时间 auto duration = duration_cast<milliseconds>(end_time - start_time); cout << "内存占用: " << mem_used_mb << " MB" << endl; cout << "CPU 时间: " << duration.count() << " 毫秒" << endl; // 输出复杂度分析 cout << "\n时间复杂度分析:" << endl; cout << "- 密钥生成: O(1)(假设输入固定)" << endl; cout << "- 加密/解密: O(log e) O(log d)(快速幂算法)" << endl; cout << "空间复杂度分析:" << endl; cout << "- 存储密钥和中间变量: O(1)" << endl; return 0; } 注意事项: 1. 在Dev C++中,可能需要链接psapi库。在项目设置中添加链接参数:-lpsapi。 2. is_prime函数是简单的试除法,仅适用于较小的数,对于大素数可能效率低下,但作为实验代码可以接受。 3. 内存占用的计算可能不准确,因为进程的内存使用会有波动,且包含整个程序的内存,而不仅仅是变量。这里计算的是整个进程的工作集内存差异,可能不完全准确,但作为实验目的可以接受。 4. CPU时间的计算可能用户想要的是程序运行的实际时间,这里用了高分辨率时钟,但实际可能受到系统调度影响。 5. 输入明文假设为整数,若需要处理字符串,需额外转换,但会增加代码复杂度。 6. 对于大数,long long可能会溢出,因此实际应用中应使用大数库,但实验代码中简化处理。 最后,用户可能需要在Dev C++中配置链接psapi库,否则会出现链接错误。具体步骤是:项目选项 -> 参数 -> 链接器,添加-psapi-lpsapi,根据编译器情况而定。</think>以下是RSA加密算法的实验代码,满足您的要求: ```cpp #include <iostream> #include <cmath> #include <windows.h> #include <psapi.h> #include <chrono> using namespace std; using namespace chrono; // 快速幂取模算法 long long mod_pow(long long base, long long exponent, long long mod) { long long result = 1; base = base % mod; while (exponent > 0) { if (exponent % 2 == 1) result = (result * base) % mod; exponent = exponent >> 1; base = (base * base) % mod; } return result; } // 扩展欧几里得算法 long long extended_gcd(long long a, long long b, long long& x, long long& y) { if (b == 0) { x = 1; y = 0; return a; } long long gcd = extended_gcd(b, a % b, x, y); long long temp = x; x = y; y = temp - (a / b) * y; return gcd; } // 求模逆元 long long mod_inverse(long long a, long long m) { long long x, y; long long gcd = extended_gcd(a, m, x, y); return (gcd == 1) ? (x % m + m) % m : -1; } int main() { PROCESS_MEMORY_COUNTERS pmc; auto start_time = high_resolution_clock::now(); long long p, q; cout << "请输入素数p q: "; cin >> p >> q; long long n = p * q; long long phi = (p - 1) * (q - 1); long long e; cout << "请输入公钥e: "; cin >> e; long long d = mod_inverse(e, phi); if (d == -1) { cout << "无效公钥!" << endl; return 1; } long long m; cout << "请输入明文: "; cin >> m; // 加密过程 long long c = mod_pow(m, e, n); // 解密过程 long long decrypted = mod_pow(c, d, n); // 获取内存信息 GetProcessMemoryInfo(GetCurrentProcess(), &pmc, sizeof(pmc)); double mem_usage = pmc.WorkingSetSize / (1024.0 * 1024.0); // 计算执行时间 auto end_time = high_resolution_clock::now(); auto duration = duration_cast<microseconds>(end_time - start_time); cout << "\n加密结果: " << c << endl; cout << "解密结果: " << decrypted << endl; cout << "内存占用: " << mem_usage << " MB" << endl; cout << "执行时间: " << duration.count() / 1000.0 << " 毫秒" << endl; cout << "\n时间复杂度分析:" << endl; cout << "1. 密钥生成: O(1)" << endl; cout << "2. 加密/解密: O(log n)(快速幂算法)" << endl; cout << "\n空间复杂度分析:" << endl; cout << "1. 固定内存消耗: O(1)" << endl; return 0; } ``` 实验流程说明: 1. 输入两个素数p和q(建议使用小于1e6的素数) 2. 输入公钥e(推荐使用65537) 3. 输入明文(整数形式) 4. 程序自动计算并显示加密、解密结果 5. 输出资源使用情况和复杂度分析 代码特性: 1. 使用快速幂算法优化计算效率 2. 包含完整的内存和性能监控 3. 支持中文交互界面 4. 包含详细的复杂度分析 注意事项: 1. 需在Dev C++中链接psapi库(项目设置→参数→链接器添加`-lpsapi`) 2. 素数建议选择3位以上(如101103) 3. 明文数字建议小于n的值 4. CPU占用显示为程序执行时间(毫秒) 复杂度分析: $$ \begin{aligned} \text{时间复杂度} &: \begin{cases} O(1) & \text{密钥生成} \\ O(\log n) & \text{加密/解密} \end{cases} \\ \text{空间复杂度} &: O(1) \end{aligned} $$
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值