0
点赞
收藏
分享

微信扫一扫

PAT 1049 C++版

琛彤麻麻 2022-01-26 阅读 71


PAT 1049 C++版

1.题意

给出一个正整数N。欲求出1~N这些数字中包括字符1的个数。

例如给出一个数12,从1到12 的数中,包含1的个数一共有5个【1,10,11,12】。

2.分析

这里给出数个简单的方法,如下:

方法一:直接暴力求解,这样在应试的情况下也可以拿到22分。

方法二:寻找某种特殊的关系 这里可见柳神的代码 ​​​https://www.liuchuo.net/archives/2305。​​​ 我心里只有一个字:膜!

我主要对柳神的代码进行一个简单的介绍。

思想如下: 考察每位取1的次数,然后将这些次数进行一个累积求和,即可得到最终结果。 如下给出一个例子。​​N=123​​。


  • step 1:先计算个位上的3,对于个位上可以取到1的次数是13次【​​001 , 011 …… 091,101, 111, 121​​】。可以看到这个关系是​​else ans += (left + 1) * a;​
  • step 2:接着计算十位上的2。可以取到20次,分别是【010—019, 110—119】。对应的关系是:​​ans += (left + 1) * a​​。
  • step 3:接着计算百位上的1。可以取到23次,分别是【100—123】。对应的关系是:​​ans += left * a + right + 1​​ 对上面的次数进行一个累加,即可得到最后的一个结果: ​​13 + 20 + 24 = 57​

3.代码

方法一的代码很简单,鄙人不再献丑。

方法二的代码如下:

#include <iostream>
using namespace std;
int main() {
int n, left = 0, right = 0, a = 1, now = 1, ans = 0;
scanf("%d", &n);
while(n / a) {
left = n / (a * 10), now = n / a % 10, right = n % a;
if(now == 0) ans += left * a;
else if(now == 1) ans += left * a + right + 1;
else ans += (left + 1) * a;
a = a * 10;
}
printf("%d", ans);
return 0;
}

5.注意

5.1

​2<<30​​​ 就是​​2^31​​次方。因为第一个数是2,而不是1.

6.参考文章

6.1 感谢柳神!



举报

相关推荐

PAT 1083 C++版

PAT 1146 C++ 版

PAT 1066 Root of AVL Tree C++版

C++解PAT A1048 Find C

c++解PAT A10878Hashing

pat b1029 c++记录

0 条评论