Uva12716Gcd=Xor

博客围绕求解满足GCD(a,b) = a XOR b(1<=b <=a<=n,1<= n <= 30000000)的问题展开。介绍了两种思路,一是利用a XOR c=b并用gcd(a,b)=c验证,但时间复杂度高;二是证明b=a - c,还给出了相关证明过程及参考链接。

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

题意:

求满足GCD(a,b) = a XOR b; 其中1<=b <=a<=n。1<= n <= 30000000.

思路:

异或:a XOR b = c 那么 a XOR c = b;
那么我们令GCD(a,b)= c; 这样 a 是 c 倍数。我们可以通过遍历c , 然后通过筛法,把c的倍数晒出当作a。求b如何求呢?

书上提供一种方法是利用a XOR c=b 然后用 gcd(a,b)=c 验证。但是这个方法是超时的,gcd是logn 级别的 总的时间复杂度,n*(logn)^2。这是我们不能接受的。

还有一种方法是证明b=a-c。这个证明还是不容易的 :

首先(a>b)gcd(a,b) = c <= a-b 其次要证明a ^ b >= a-b 。我们可以这样想,他们什么时候取等于,我们知道异或是相同为0,不同为1 那么 我们把a,b用二进制展开,这样我们a,b是每一位对应的,我们把所以不同的二进制位,全部变为ai = 1,bi = 0。这样我们知道,没有借位 那么a ^ b == a-b 。那么后面按照XOR序列的顺序变化,a-b变小,那么a ^ b >= a-b。从而c = a-b
参考:http://www.mamicode.com/info-detail-2490991.html

#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cmath>
//#include <iostream>
#include <algorithm>
using namespace std;
typedef long long LL;
const int RA = 30000000;

int ans[RA + 5];

void Init(){
	memset(ans,0,sizeof(ans));
    for(int c = 1; c <= RA/2; ++c){
        for(int a = c + c; a <= RA; a += c){
            int b = a - c;
            if((a ^ b) == c) ++ans[a];
        }
    }
    for(int i = 2; i <= RA; ++i) ans[i] += ans[i - 1];
}

int main(){
	
    Init();
    //freopen("in.txt","r",stdin);
    int T,N; 
    scanf("%d",&T);
    for(int i = 1; i <= T; ++i){
        scanf("%d",&N);
        printf("Case %d: %d\n",i,ans[N]);
    }
    return 0;
}
%% XOR加密 ================================================== function [encrypted, nonce] = XOR_Encrypt(plaintext, key) % 生成8字节随机数(64位nonce) nonce = uint8(randi([0 255], 1, 8)); % 将输入文本转换为UTF-8字节流 dataBytes = unicode2native(plaintext, 'UTF-8'); dataBytes = uint8(dataBytes); % 密钥扩展(与数据等长) expandedKey = XOR_KeyExpansion(key, nonce, length(dataBytes)); % 异或加密(自动处理数组尺寸) encrypted = bitxor(dataBytes, expandedKey(1:length(dataBytes))); encrypted = encrypted(:).'; % 确保行向量输出 end function decrypted = XOR_Decrypt(ciphertext, key, nonce) % 强制类型转换并验证输入 ciphertext = uint8(ciphertext(:)'); % 确保行向量 % 密钥扩展(与密文等长) expandedKey = XOR_KeyExpansion(key, nonce, length(ciphertext)); % 异或解密 decryptedBytes = bitxor(ciphertext, expandedKey(1:length(ciphertext))); % 转换为Unicode字符串 decrypted = native2unicode(decryptedBytes, 'UTF-8'); end function expandedKey = XOR_KeyExpansion(key, nonce, requiredLength) import javax.crypto.Mac; import javax.crypto.spec.SecretKeySpec; % 初始化HMAC-SHA256 hmac = Mac.getInstance('HmacSHA256'); secretKey = SecretKeySpec(unicode2native(key, 'UTF-8'), 'HmacSHA256'); hmac.init(secretKey); expandedKey = uint8([]); counter = 1; % 密钥扩展循环 while length(expandedKey) < requiredLength % 构造输入:nonce + 计数器(4字节大端序) counterBytes = typecast(swapbytes(int32(counter)), 'uint8'); input = [uint8(nonce) counterBytes]; % 生成密钥块 block = hmac.doFinal(input); expandedKey = [expandedKey uint8(block(:)')]; counter = counter + 1; end end修改函数以支持二进制数据,给出完整代码
最新发布
03-16
<think>嗯,用户让我修改现有的XOR加密MATLAB函数,以支持二进制数据。首先,我需要理解现有的代码结构以及为什么它可能不支持二进制数据。原代码中,加密和解密函数处理的是文本,使用unicode2native和native2unicode进行转换,这可能将二进制数据错误地转换为字符,导致数据损坏。 首先,检查加密函数XOR_Encrypt。它接受plaintext作为输入,并将其转换为UTF-8字节流。如果用户传入的是二进制数据(比如图像、已加密的文件等),直接使用unicode2native可能会出错,因为二进制数据可能包含无效的UTF-8序列。所以需要修改输入参数的处理,直接接受uint8类型的二进制数据,而不是强制转换字符串。 同样,解密函数XOR_Decrypt目前将解密后的字节转换为Unicode字符串,这对于二进制数据来说是不合适的,应该直接返回uint8数组。因此,需要移除native2unicode的转换步骤,并确保输出保持为uint8。 密钥扩展函数XOR_KeyExpansion中,处理密钥时使用unicode2native,这可能没问题,因为密钥通常是字符串,但需要确认用户是否可能传递二进制密钥。不过根据常规用法,密钥可能还是字符串,所以暂时保留这部分,但可能需要注释说明。 接下来,修改函数参数。将XOR_Encrypt的plaintext参数允许接受uint8数组,如果是字符串则按原方法转换。加密后的输出直接是uint8。同样,XOR_Decrypt的ciphertext应该直接处理uint8,解密后返回uint8而不是字符串。 需要添加输入验证,比如检查plaintext是否为字符串或uint8数组。在加密函数中,如果输入是字符串,按原方法转UTF-8;如果是uint8,直接使用。解密函数则不需要转换,直接处理uint8,输出也是uint8。 此外,确保nonce生成部分正确,返回uint8数组。密钥扩展部分可能不需要修改,因为它处理的是字节流。 测试用例部分,用户可能需要例子来展示如何加密二进制数据,比如图像矩阵,或者任意字节流。需要添加注释说明函数的修改和用法。 最后,确保代码中的类型转换正确,避免行向量和列向量的不一致,使用(:).'来确保行向量输出。 综上,修改步骤包括:调整输入输出处理、添加类型检查、移除不必要的字符串转换,并更新文档说明。</think>以下是修改后支持二进制数据的完整代码(包含详细的中文注释和类型验证): ```matlab %% XOR加密/解密函数(支持二进制数据) % 修改点:取消字符串强制转换,添加二进制数据处理逻辑 function [encrypted, nonce] = XOR_Encrypt(plaintext, key) % 生成8字节随机数(64位nonce) nonce = uint8(randi([0 255], 1, 8)); % 输入类型验证与转换(核心修改) if ischar(plaintext) dataBytes = unicode2native(plaintext, 'UTF-8'); % 字符串转UTF-8 elseif isa(plaintext, 'uint8') dataBytes = plaintext; % 直接使用二进制输入 else error('输入类型错误:仅支持字符串或uint8数组'); end dataBytes = uint8(dataBytes); % 密钥扩展(与数据等长) expandedKey = XOR_KeyExpansion(key, nonce, length(dataBytes)); % 异或加密(自动处理数组尺寸) encrypted = bitxor(dataBytes, expandedKey(1:length(dataBytes))); encrypted = encrypted(:).'; % 确保行向量输出 end function decrypted = XOR_Decrypt(ciphertext, key, nonce) % 强制类型转换并验证输入(核心修改) ciphertext = uint8(ciphertext(:)'); % 确保行向量 if ~isa(ciphertext, 'uint8') error('密文必须是uint8数组'); end % 密钥扩展(与密文等长) expandedKey = XOR_KeyExpansion(key, nonce, length(ciphertext)); % 异或解密 decryptedBytes = bitxor(ciphertext, expandedKey(1:length(ciphertext))); % 取消自动转换(保留二进制输出) decrypted = decryptedBytes; % 直接返回uint8数组 end %% 密钥扩展函数(未修改,保持原逻辑) function expandedKey = XOR_KeyExpansion(key, nonce, requiredLength) import javax.crypto.Mac; import javax.crypto.spec.SecretKeySpec; % 初始化HMAC-SHA256 hmac = Mac.getInstance('HmacSHA256'); secretKey = SecretKeySpec(unicode2native(key, 'UTF-8'), 'HmacSHA256'); hmac.init(secretKey); expandedKey = uint8([]); counter = 1; % 密钥扩展循环 while length(expandedKey) < requiredLength % 构造输入:nonce + 计数器(4字节大端序) counterBytes = typecast(swapbytes(int32(counter)), 'uint8'); input = [uint8(nonce) counterBytes]; % 生成密钥块 block = hmac.doFinal(input); expandedKey = [expandedKey uint8(block(:)')]; counter = counter + 1; end end ``` 主要改进说明(通过表格对比): | 原功能限制 | 新功能实现 | 修改位置 | |--------------------|--------------------------|-----------------------| | 仅支持字符串输入 | 支持uint8二进制数据 | XOR_Encrypt输入验证 | | 自动转换输出字符串 | 保留二进制输出 | XOR_Decrypt返回类型 | | 缺少类型验证 | 添加输入类型检查 | 两个函数开头验证逻辑 | | 可能的数据损坏 | 保持原始二进制数据完整性 | 取消native2unicode调用 | 使用示例: ```matlab %% 字符串加密 [enc, nonce] = XOR_Encrypt('Hello World', '密码'); dec = XOR_Decrypt(enc, '密码', nonce); disp(char(dec)) % 显示解密字符串 %% 二进制加密(例如加密图像数据) img = imread('test.jpg'); binData = typecast(img(:), 'uint8'); % 将图像转换为字节流 [encImg, nonce] = XOR_Encrypt(binData, '密码'); decImg = typecast(XOR_Decrypt(encImg, '密码', nonce), class(img)); % 还原数据类型 ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值