NOIP模拟题——数页码
问题描述
一本书的页码是从1-n编号的连续整数:1,2,3,……,n。请你求出全部页码中所有单个数字的和,例如第123页,它的和就是1+2+3=6。
输入数据
一行为n(1<=n<=10^9)。
输出数据
一行,代表所有单个数字的和。
样例输入
3456789
样例输出
96342015
先打表求n位数的数字和,然后递推。
可以找到第n位的代价的求法。见代码:
1 #include<cstdio> 2 #include<iostream> 3 #include<cstring> 4 #include<ctime> 5 #include<cstdlib> 6 using namespace std; 7 int n;long long ans; 8 long long a[20]; 9 inline int solve(int x) 10 { 11 int an=0; 12 while(x) 13 { 14 an=an+x%10; 15 x/=10; 16 } 17 return an; 18 } 19 int main() 20 { 21 freopen("count.in","r",stdin); 22 freopen("count.out","w",stdout); 23 scanf("%d",&n); 24 if(n<=1e7) 25 { 26 for(int i=1;i<=n;i++) 27 ans+=solve(i); 28 printf("%d",ans); 29 exit(0); 30 } 31 a[1]=45;a[2]=900;a[3]=13500;a[4]=180000; 32 a[5]=2250000;a[6]=27000000;a[7]=315000000; 33 a[8]=3600000000LL; 34 if(n<1e8) 35 { 36 long long temp=1e7,pos=7; 37 while(pos) 38 { 39 int k1=n/temp;//第一位 40 k1--; 41 ans+=(long long)temp*(long long)k1*(long long)(k1+1)/2; 42 ans+=(long long)(k1+1)*(long long)a[pos]; 43 ans+=(long long)(k1+1)*(long long)(n%temp+1); 44 n%=temp; 45 temp/=10; 46 pos--; 47 } 48 ans+=(long long)n*(long long)(n+1)/2; 49 printf("%I64d",ans); 50 exit(0); 51 } 52 if(n<1e9) 53 { 54 long long temp=1e8,pos=8; 55 while(pos) 56 { 57 int k1=n/temp;//第一位 58 k1--; 59 ans+=(long long)temp*(long long)k1*(long long)(k1+1)/2; 60 ans+=(long long)(k1+1)*(long long)a[pos]; 61 ans+=(long long)(k1+1)*(long long)(n%temp+1); 62 n%=temp; 63 temp/=10; 64 pos--; 65 } 66 ans+=(long long)n*(long long)(n+1)/2; 67 printf("%I64d",ans); 68 exit(0); 69 } 70 printf("40500000001"); 71 return 0; 72 }