题目:
"3"是一个很奇妙的数字,阿尔萨斯作为war3里的英雄,对“3”很感兴趣,他很想让"3"越多越好。 一天,阿尔萨斯发现手下站成了n个军团,第i个军团正好有i个人,于是他把所有军团的人数连续写成了一个长串(123456...),现在阿尔萨斯想知道,其中"3"出现了多少次,你能帮帮他吗?
题意:
输入一个n,求从1到n有多少个三。
思路:
整体思路:从个位开始,求当前位数能有多少个三,记录下来,再推下一位,直到最后一位,对于当前位数,3的个数由新出的一位数上3的个数,和前几位数出现3的个数相加得到。
举个例子,4567;
个位是7>3,sum=1,sum1=1(sum1是在记录前几位出现了多少次三).
十位:0-9出现一次3,0-5进行6次循环,所以从0-60是6*1个3,60-67是sum1,还有新出的十位上3,6>3,3_有10种情况,所以共17种情况sum1=17.
百位:0-99,20种情况,0-4,5次循环,0-500,是20*5个3,500-576是sum1,百位上的3,5>3,3_ _有100种情况,sum1=217.
千位:0-999,300种情况,0-3,4次循环,0-4000,是4*300个3,4000-4567是sum1,千位上的4>3,3_ _ _有1000种情况,sum1=2417.
答案即为2417.
对当前位判断还有比如:3567,因为3==3,3_ _只有000-567共568情况,所以sum1=1985;
2567,2<3,千位没有3_ _情况,所以sum1=1417.
代码:
#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <queue>
#include<algorithm>
#include<cmath>
#include<map>
#include<string.h>
#include<string>
#include<cstring>
#include<utility>
#include<queue>
using namespace std;
const long long MAX = 1e6;
long long n, x1, i, j,sum,sum1,x,m,k,cnt,sum2;
long long y;
int main()
{
while (cin >> n)
{
k = 1;
sum1 = 0;
x1 = (int)log10(n)+1;//计算有多少位
if ( n%10>= 3)
sum1 = 1;
else
sum1 = 0;//个位的计算
for (int i = 2; i <= x1; i++)//十位之后的计算
{
k *= 10;//k是10,1000,10000....
sum = 0;
x = i-1;
for (int j = 1; j + 1 < 1 << (i-1); j++)
{
cnt = 0;
sum2 = 1;
for (int k = 0; k <i; k++)
if (j & 1 << k)
cnt++;
for (int b = 1; b <= cnt; b++)
sum2 *= 9;
sum2 *= (i - 1 - cnt);
x += sum2;
}//由2进制暴力枚举计算_ _ _i-1位有多少个3.
m = n;
m=m / k;
sum += x * (m % 10) + sum1;//计算前几位有多少个3.
if (m % 10 == 3)
sum += n % k + 1;
else if (m % 10 > 3)
sum += k;//计算新出的一位有多少个3.
sum1 = sum;
}
cout << sum << endl;
}
return 0;
}
文章描述了一个基于数字分析的问题,阿尔萨斯(来自war3游戏)想要知道从1到n的序列中数字3出现的次数。通过逐位分析,计算每个位上3可能出现的次数,并累加得到总数。文中提供了具体的计算逻辑和示例,并给出了C++代码实现。





