洛谷P1590 失踪的7

题目描述

远古的Pascal人也使用阿拉伯数字来进行计数,但是他们又不喜欢使用7,因为他们认为7是一个不吉祥的数字,所以Pascal数字8其实表示的是自然数中的7,18表示的是自然数中的16。下面计算一下,在正整数n范围以内包含有多少个Pascal数字。

输入输出格式

输入格式:

第一行为正整数t,接下来t行,每行一个正整数n(≤2^32-1)。

输入的是Pascal数字

输出格式:

对于每个正整数n,输出n以内的Pascal数的个数。

##输入输出样例

输入样例#1:

2
10
20

输出样例#1:

9
18

思路

虽然是个入门题但是不想写暴力,
于是开始xjb搞事情什么的QWQ
所以鱼块地发题解了,
以下用了一种十分奇怪的解法,叫做:进制转换!!

首先,Pascal数字是由0,1,2,3,4,5,6,8,9 九个数字组成的
所以我们很(不)容易想到Pascal数字可以近似的看成一种九进制数
所以题面:
在正整数n范围以内包含有多少个Pascal数字
就可以看作:
读入一个Pascal数 ,转为普通数字
即读入一个九进制数,转为十进制(我的理解QWQ)
//当然还是满十进一但是7消失了QWQ

所以我写了这样的代码

代码1:

//九进制转十进制 
#include <iostream>
#include <cstring>
using namespace std;
long long k,ans=0;
int t,i;
char a[1001];
int main()
{
	cin>>t;
	while (t--)
	{
		ans=0;
	    cin>>a;
		k=strlen(a);
		for (i=0;i<k;++i) ans=ans*9+a[i]-'0';
		cout<<ans<<endl;
	}
}

然后很容易发现出了Bug,即WA了TUT
Bug是什么呢??
当我们把题目抽象成 九进制转十进制 时,是把1~n中所有含数位9的数字判定为非Pascal数,而不是题目要求的7
就是当读入的数据中含有7,8,9时,应该被判定为非Pascal数的含数位7的数被判定为了Pascal数
而当读入数据中不含7,8,9时,7的出现就和9的出现相匹配
即 9
所以我们需要一个特判,将多计算的Pascal数减去QWQ

代码

#include <iostream>
#include <cstring>
using namespace std;
long long k,s=1,sum=0,ans=0;
int t,i,j;
char a[1001];
int main()
{
	cin>>t;
	while (t--)
	{
		ans=sum=0;
		s=1;
	    cin>>a;
		k=strlen(a);
		//以下若干行是特判QWQ
		for (i=0;i<k;++i)
		/*
		    如果读入的数的某个数位是7
			那么意味着 
			    假设读入abcd7efgh(a,b,c,d都不是7), 
			    那么从 abcd70000 到 abcd7efgh 都不是Pascal数
				那么其结果就与 abcd69999 相同 
		    such as 700
		    其运行结果和699 完全一致
			5789898984 和 5699999999 运行结果完全一致
			把这个数从最高位到最低位扫一遍,如果该位是7,就把7替换为6,之后数位替换为9 
	    */ 
		    if (a[i]=='7')
		    {
		    	a[i]='6';
		    	for (j=i+1;j<k;++j) a[j]='9';
		    	break;
			}
		for (i=k-1;i>=0;--i)
		/* 
		     减去应该被消去却【划掉】因进制转换的不合理性【划掉】被保留的数字的个数:
		     如果一个数的个位是8或9,就少减了9^0个7
			 如果一个数的十位是8或9,就少减了9^1个7
			 如果一个数的百位是8或9,就少减了9^2个7
			 ...以此类推
			 是个比较明显的找规律,不想写证明QWQ
		*/
		{
			if (a[i]>'7') sum+=s;
			s*=9;
		}
		for (i=0;i<k;++i) ans=ans*9+a[i]-'0';
		cout<<ans-sum<<endl;
	}
} 
//其实代码2确实是凑出来的TUT
//但还是完结撒花~~ 

脑洞做法(

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值