题目描述
远古的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
//但还是完结撒花~~
脑洞做法(