C++编程题之将功赎过和约德尔测试

本文介绍两道有趣的在线编程题目,一是通过计算二进制中1的数量来破解密码的尝试次数;二是通过比较两个字符串来评估约德尔人未来的相似率。

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

这两道题是在某网站做在线编程题遇到的,感觉挺有意思。以下是原版问题描述。
问题1:将功赎过:
小赛是一名幸运的程序员。
虽然他成功帮助小朋友以最快时间夺回了狼堡,但是面试官却打算和他说拜拜了。
理由是——游戏天赋太高,有不务正业、走火入魔的倾向QAQ……
尽管小赛很不能接受这个理由,可是却只能心灰意冷地吃下这个结果。
然而,在他即将走出门的时候,面试官给了幸运的小赛一个最后的机会。
原来,面试官的手机被他调皮的儿子小明用一个数字作为密码锁上了。
小明只记得这个数字的十进制范围是l~r,且这个数的二进制表示中恰有m个1,却不记得确切的数字了。
面试官可急坏了。这才有了小赛一个将功赎过的机会。
他想要让小赛算出,他最坏情况下,要试多少次密码才能确保打开手机呢?
请输出这个次数。
输入
输入仅一行,包含三个整数l,r,m,其中l,r表示这个数的十进制范围是l~r,m表示这个数的二进制表示中有m个1.
数据保证——
对于30%的测试点,0<=l<=r<=20,0<=m<=5,
对于70%的测试点,0<=l<=r<=1000,0<=m<=10,
对于100%的测试点,0<=l<=r<=2000000,0<=m<=24.
输出
输出一行,包含一个整数,表示面试官最坏情况下,要试多少次密码才能确保打开手机。
如果小明记错了(也就是不存在任何一个数满足),则输出"-1"(不含引号)。

以下是我的代码:

#include<iostream>
using namespace std;
int cnt_one(int i)
{ 
 	int sum=0; 
	while(i)
	{
		//这步很重要,仔细理解
		i=i&(i-1);  
		sum++; 
	} 
  	return sum;
}
int main()
{
  int l,r,m,i,num;
  while(cin>>l>>r>>m)  
  {
    if(l<0||r<0||l>r||l>2000000||r>2000000||m<0||m>24)  return 0;    
	num=0;
    for(i=l;i<=r;i++)    
    {
		if(cnt_one(i)==m)
			num++;    
	}
    if(num>0)      
      cout<<num<<endl;    
    else      
      cout<<-1<<endl;  
  }
  return 0;
}

问题2:约德尔测试
兰博和提莫闲聊之后,回归到了他们的正题,约德尔人的未来。
说起约德尔人的未来,黑默丁格曾经提出了一个约德尔测试,将约德尔人的历史的每个阶段都用一个字符表达出来。(包括可写字符,不包括空格。)。然后将这个字符串转化为一个01串。转化规则是如果这个字符如果是字母或者数字,这个字符变为1,其它变为0。然后将这个01串和黑默丁格观测星空得到的01串做比较,得到一个相似率。相似率越高,则约德尔的未来越光明。
请问:相似率为多少?
输入
每组输入数据为两行,第一行为有关约德尔人历史的字符串,第二行是黑默丁格观测星空得到的字符串。
(两个字符串的长度相等,字符串长度不小于1且不超过1000。)
输出
输出一行,在这一行输出相似率。用百分数表示。(相似率为相同字符的个数/总个数,精确到百分号小数点后两位。printf("%%");输出一个%。)

以下我的代码(String类型确实方便):

#include<iostream>
#include<string>
#include<iomanip>
using namespace std;

double furtureP(string future, string stars)
{
	int numF = future.size();
	int numS = stars.size();
	int simNum = 0;
	if (numF != numS)
	{
		return 0;
	}
	if (numF<1 || numF>1000)
	{
		return 0;
	}
	for (int i = 0; i<numF; i++)
	{
		if ((future[i]>='a'&& future[i]<='z') || (future[i]>='A'&&future[i]<='Z') || (future[i]>='0' && future[i]<='9'))
		{
			if (stars[i] == '1')
			{
				simNum++;
			}
		}
		else
		{

			if (stars[i] == '0')
			{
				simNum++;
			}
		}
	}
	double simPrecent = 0;
	simPrecent = double(simNum) / double(numF);
	return simPrecent;
}
int main()
{
	double precent = 0.0;
	string sF, sS;
	while (cin >> sF >> sS)
	{
		precent = furtureP(sF, sS);
		cout << setiosflags(ios::fixed);
		cout << setprecision(2) << precent * 100 << "%" << endl;
	}
	return 0;
}

某大神代码(膜拜一下)

#include<iostream>
#include<cstdlib>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<string>
using namespace std;
string a,b;
bool isAlph(char &c) {
  return ((c>='a'&&c<='z')||(c>='A'&&c<='Z'));
}
bool isNum(char &c) {
  return (c>='0'&&c<='9');
}
bool isOne(char &c) {
  return (isAlph(c)||isNum(c));
}
int main () {
  cin>>a>>b;
  int l = a.length();
  int cnt = 0;
  for(int i=0;i<l;++i) {
    if(isOne(a[i])^(b[i]=='1'))
      continue;
    ++cnt;
  }
  double ans = cnt*100.0/l;
  printf("%.2lf%%\n", ans);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

林多

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值