news 2026/5/19 14:22:55

UVa 128 Software CRC

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
UVa 128 Software CRC

题目描述

你在一家大量使用个人电脑的公司工作。老板Penny Pincher\texttt{Penny Pincher}Penny Pincher博士一直想将这些电脑连接起来,但又不愿意花钱购买你建议的以太网卡。你无意中提到每台PC\texttt{PC}PC都自带一个异步串行口(无需额外费用),于是老板抓住机会,让你编写必要的软件来实现PC\texttt{PC}PC间的通信。

你了解到通信过程中容易出错,典型的解决方案是在每条消息末尾附加错误校验信息,以便接收程序能检测到传输错误(大多数情况下)。经过研究,你决定采用**CRC\texttt{CRC}CRC(循环冗余校验)**作为错误校验机制,并向老板提交了如下方案:

CRC\texttt{CRC}CRC生成机制

待传输的消息被视为一个很长的正二进制数。消息的第一个字节是该二进制数的最高有效字节,第二个字节是次高有效字节,依此类推。这个二进制数称为mmmmessage\texttt{message}message)。实际传输的不是mmm,而是一个新消息m2m_2m2,它由mmm和紧随其后的两字节CRC\texttt{CRC}CRC值组成。

CRC\texttt{CRC}CRC值的选取原则是:m2m_2m2除以某个161616位值ggg(生成器)的余数为000。这样接收程序只需将收到的消息除以ggg,若余数为000就认为没有发生传输错误。

你在书中发现大多数建议的ggg值都是奇数,但没有其他明显规律,因此你选择了g=34943g = 34943g=34943(十进制)作为生成器。

你的任务是设计一个算法,计算任意待发送消息对应的CRC\texttt{CRC}CRC值,并编写程序进行测试。

输入格式

每行输入包含不超过102410241024ASCII\texttt{ASCII}ASCII字符(每行字符不包括换行符)。
输入以第一列为#的行结束。

输出格式

对每个输入行,计算该行消息的CRC\texttt{CRC}CRC值,并以十六进制形式输出两个字节的CRC\texttt{CRC}CRC值(中间用空格分隔)。
注意每个CRC\texttt{CRC}CRC值应在000349423494234942(十进制)范围内。


题目分析与解题思路

本题的核心是计算给定消息的161616CRC\texttt{CRC}CRC校验码,使得附加CRC\texttt{CRC}CRC后的整个消息(视为一个大整数)能被g=34943g = 34943g=34943整除。

数学模型

设消息mmmkkk个字节组成:bk−1,bk−2,…,b0b_{k-1}, b_{k-2}, \dots, b_0bk1,bk2,,b0(其中bk−1b_{k-1}bk1是最高有效字节)。
mmm视为一个256256256进制的数,即:

m=bk−1⋅256k−1+bk−2⋅256k−2+⋯+b0⋅2560 m = b_{k-1} \cdot 256^{k-1} + b_{k-2} \cdot 256^{k-2} + \dots + b_0 \cdot 256^0m=bk1256k1+bk2256k2++b02560

附加两字节CRC\texttt{CRC}CRCccc0≤c<655360 \le c < 655360c<65536)后,得到新消息:

m2=m⋅65536+c m_2 = m \cdot 65536 + cm2=m65536+c

要求m2mod g=0m_2 \mod g = 0m2modg=0,即:

(m⋅65536+c)mod g=0 (m \cdot 65536 + c) \mod g = 0(m65536+c)modg=0

因此:

c=(g−(m⋅65536)mod g)mod g c = (g - (m \cdot 65536) \mod g) \mod gc=(g(m65536)modg)modg

注意ccc应输出为两个字节,即ccc000655356553565535之间,但题目保证g=34943g = 34943g=34943,所以c<gc < gc<g,自然满足。

算法设计

直接计算mmm可能非常大(最多102410241024字节,即281922^{8192}28192量级),必须边读边模ggg运算。

我们可以从最低有效字节开始计算mmod gm \mod gmmodg

设当前余数为rrr(初始为000),逐个处理字节bib_ibi(从最后一个字节开始向前):

r=(r+bi⋅256i)mod g r = (r + b_i \cdot 256^i) \mod gr=(r+bi256i)modg

256i256^i256i也会很大,需要预先计算256imod g256^i \mod g256imodg的模幂值。

可以预先计算了一个数组modular[i],其中:

modular[i] = (65536 * 256^i) mod g

注意这里65536 = 256^2,是因为在计算m⋅65536m \cdot 65536m65536时,相当于将mmm左移161616位(即乘以655366553665536)。代码中从最低字节开始累加时,直接使用了modular[j],其中jjj是当前字节的索引(从000开始)。

计算步骤

  1. 预处理modular[0..1024],其中modular[0] = 65536 mod gmodular[i] = (modular[i-1] * 256) mod g
  2. 对每个输入行(非空且不以#开头):
    • 从字符串末尾开始向前遍历(即从最低有效字节向最高有效字节)。
    • 对于位置jjj(从000开始)的字符line[i],累加(line[i] * modular[j]) mod g到余数residue
    • 遍历完成后,residue即为(m⋅65536)mod g(m \cdot 65536) \mod g(m65536)modg
    • 计算c = (g - residue) mod g
    • c转换为两个字节的十六进制输出。

边界情况

  • 空行:CRC\texttt{CRC}CRC值为00 00
  • 输入结束:第一列为#的行。

代码实现

// Software CRC// UVa ID: 128// Verdict: Accepted// Submission Date: 2015-12-01// UVa Run Time: 0.352s//// 版权所有(C)2015,邱秋。metaphysis # yeah dot net#include<bits/stdc++.h>usingnamespacestd;constintMOD_BASE=34943;intmodular[1030];// 预处理 modular 数组:modular[i] = (65536 * 256^i) % MOD_BASEvoidgenerateModular(){modular[0]=65536%MOD_BASE;for(inti=1;i<=1024;i++)modular[i]=(modular[i-1]*256)%MOD_BASE;}// 将16位CRC值转换为两个字节的十六进制形式输出voidintToHex(intresidue){string hex="0123456789ABCDEF";cout<<hex[residue/256/16];cout<<hex[residue/256%16];cout<<" ";cout<<hex[(residue%256)/16];cout<<hex[residue%256%16];cout<<endl;}// 计算一行消息的CRC并输出voidsoftwareCRC(string line){intresidue=0;// 从最低有效字节开始累加for(inti=line.length()-1,j=0;i>=0;i--,j++)residue+=(line[i]*modular[j]%MOD_BASE);// 计算CRC值residue=(MOD_BASE-residue%MOD_BASE)%MOD_BASE;intToHex(residue);}intmain(intac,char*av[]){generateModular();string line;while(getline(cin,line)){if(line.length()==0){cout<<"00 00"<<endl;continue;}if(line[0]=='#')break;softwareCRC(line);}return0;}

样例说明

输入:

this is a test A #

输出:

77 FD 00 00 0C 86
  • 第一行消息"this is a test"CRC\texttt{CRC}CRC0x77FD
  • 第二行"A"的CRC为0x0C86
  • 空行输出00 00

总结

本题是一个典型的CRC\texttt{CRC}CRC校验码计算问题,关键在于理解消息被视为一个大整数,以及模运算在避免大数计算中的应用。通过预处理256imod g256^i \mod g256imodg的值,可以高效地逐字节计算余数,最终得到两字节的CRC\texttt{CRC}CRC校验码。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/5/19 0:36:59

海尔智能家居集成完整配置指南

海尔智能家居集成完整配置指南 【免费下载链接】haier 项目地址: https://gitcode.com/gh_mirrors/ha/haier 海尔Haier智能家居集成是HomeAssistant中功能最全面的海尔设备连接解决方案&#xff0c;能够将您家中的所有海尔智家设备无缝接入智能家居系统。这个强大的集成…

作者头像 李华
网站建设 2026/5/19 3:45:56

高并发场景应对:OCR服务负载均衡配置方案

高并发场景应对&#xff1a;OCR服务负载均衡配置方案 &#x1f4d6; 项目简介与技术背景 随着数字化进程的加速&#xff0c;OCR&#xff08;光学字符识别&#xff09; 技术在发票识别、文档电子化、智能客服等场景中扮演着越来越关键的角色。尤其是在企业级应用中&#xff0c;单…

作者头像 李华
网站建设 2026/5/11 21:44:14

新手必备:5分钟学会用gifski制作高清GIF动画的完整教程

新手必备&#xff1a;5分钟学会用gifski制作高清GIF动画的完整教程 【免费下载链接】gifski GIF encoder based on libimagequant (pngquant). Squeezes maximum possible quality from the awful GIF format. 项目地址: https://gitcode.com/gh_mirrors/gif/gifski 还在…

作者头像 李华
网站建设 2026/5/12 21:24:32

告别混乱:脚本窗口管理效率提升300%的方案

快速体验 打开 InsCode(快马)平台 https://www.inscode.net输入框内输入如下内容&#xff1a; 实现一个高效的窗口管理器类&#xff0c;具有以下功能&#xff1a;1. 使用WeakMap自动跟踪所有打开的窗口 2. 提供按条件过滤关闭窗口的能力&#xff08;如只关闭特定域名窗口&…

作者头像 李华
网站建设 2026/5/16 7:52:27

零基础教程:5分钟学会CAD批量打印插件安装使用

快速体验 打开 InsCode(快马)平台 https://www.inscode.net输入框内输入如下内容&#xff1a; 设计一个极简版的CAD批量打印插件&#xff0c;要求&#xff1a;1.三步完成安装&#xff08;下载-运行-重启CAD&#xff09;&#xff1b;2.直观的拖放式操作界面&#xff1b;3.内置…

作者头像 李华
网站建设 2026/5/12 23:15:01

好写作AI:你的“原创发动机”,查重率低于5%是如何实现的?

还在用“同义词替换”对抗查重算法&#xff1f;真正的高手&#xff0c;在起跑线上就已经赢了。深夜的电脑前&#xff0c;你瞪着屏幕上27%的查重报告&#xff0c;双眼发红。你已经用尽了毕生语文功力&#xff1a;主动改被动、长句拆短句、专业词换“大白话”……可那些该死的红色…

作者头像 李华