时间: 1000ms / 空间: 131072KiB / Java类名: Main
描述
请统计某个给定范围[L, R]的所有整数中,数字2 出现的次数。
比如给定范围[2, 22],数字2 在数2 中出现了1 次,在数12 中出现1 次,在数20 中出
现1 次,在数21 中出现1 次,在数22 中出现2 次,所以数字2 在该范围内一共出现了6
次。
输入格式
输入共1 行,为两个正整数L 和R,之间用一个空格隔开。
测试样例1
输入
【输入样例1】
2 22
【输入样例2】
2 100
输出
输出样例1:
6
输出样例2:
20
备注
【数据范围】
0 ≤ L ≤ R≤ 10^10。NOIP2010普及组复赛——NO.1
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
long long i,j,n,m,len1,len2,a[13],b[13],sum1,sum2;
long long ans[110];
long long num[20];
char s[13];
int main()
{
scanf("%lld%lld",&n,&m);
sprintf(s,"%lld",n-1);
len1=strlen(s);
for (i=1;i<=len1;i++)
a[i]=s[i-1]-48;
sprintf(s,"%lld",m);
len2=strlen(s);
for (i=1;i<=len2;i++)
b[i]=s[i-1]-48;
num[1]=1; num[2]=20; num[3]=300; num[4]=4000; num[5]=50000;
num[6]=600000; num[7]=7000000; num[8]=80000000; num[9]=900000000;
for (i=1;i<=len1-1;i++)
if (a[i]==2)
{
sum1+=a[i]*num[len1-i];
long long y=0;
for (j=i+1;j<=len1;j++)
y=y*10+a[j];
y++;
sum1+=y;
}
else
if (a[i]<2)
sum1+=a[i]*num[(len1-i)];
else
{
long long y=9-a[i]+1;
sum1+=num[len1-i+1]-y*num[len1-i];
}
if (a[len1]>=2)
sum1++;
for (i=1;i<=len2-1;i++)
if (b[i]==2)
{
sum2+=b[i]*num[len2-i];
long long y=0;
for (j=i+1;j<=len2;j++)
y=y*10+b[j];
y++;
sum2+=y;
}
else
if (b[i]<2)
sum2+=b[i]*num[(len2-i)];
else
{
long long y=9-b[i]+1;
sum2+=num[len2-i+1]-y*num[len2-i];
}
if (b[len2]>=2)
sum2++;
if (n==0) sum1=0;
printf("%lld",sum2-sum1);
}//如果数据范围小,可以一个个统计,暴力一下。但是10^10显然承受不起。所以就找了一下规律,然后把每个数分解为我们已知的数,进行求解即可,处理2打头的数时要特别注意