Time Limit: 1000MS | Memory Limit: 65536K | |
Total Submissions: 9276 | Accepted: 5743 |
Description
Input
Output
Sample Input
13 15 2003 2005 239 250 1399 1500 999999 0
Sample Output
13: 12 15: 13 2003: 1461 2005: 1462 239: 197 250: 198 1399: 1052 1500: 1053 999999: 531440
Source
題目大意:有個計程器,它遇到4會跳過去(只要數字裏含4就會跳過去),如123,+1的話本應該是124,但它跳過去之後是125;如399跳過去後是500。給你一個跳過去之後的數,讓你求這個數實際上是多少?
解題思路:輸入n,相當於求1~n中不帶4的數的個數。如求13599,我們這樣看:
①13599->10000,先求10000以內的不含四的數的個數:那麼這些數相當於0xxxx這樣,0xxxx這樣的數中,根據排列組合,只含一個4的數有c(4,1)*9*9*9種(一個位置選4,其餘3個位置的選0~9中不是四的數就行),只含兩個4的數的個數爲c(4,2)*9*9,只含3個4的數的個數爲c(4,3)*9,含4個4的數的個數爲c(4,4)這樣,10000以內含四的數有1*(c(4,1)*9*9*9+c(4,2)*9*9+c(4,3)*9+c(4,4));
②求10000到13000中含四的數的個數,相當於求0~3000中含四的數的個數,然後就是類似於①了,化爲求3000內含四的數的個數:3*(c(3,1)*9*9+c(3,2)*9+c(3,3)),前面乘的三是說3000內第一位可以是0,1,2.
③求13000到13500中含4的數的個數:相當於求0~500中含四的數的個數,結果是5*(c(2,1)*9+c(2,2))+100-(c(2,1)*9+c(2,2)),+100是說最高位爲4,那麼就有100中情況,-(c(2,1)*9+c(2,2))是說之前5倍的(c(2,1)*9+c(2,2))多算了4開頭的數的個數,那麼結果就是(5-1)*(c(2,1)*9+c(2,2))+100.
④求13500~13590...
⑤求13590~13599
算出後用n-含四的數的個數就得出結果了。
注意題目中說輸入保證不含4.
綜合下:對於每一位數x,設這個數所在位數爲i(1<=i<=最高位),若x>4則貢獻爲(x-1)*(∑c(i-1,k)*pow(9,i-1-k)(k∈(1,i-1)))+pow(10,i-1);
若x<4則貢獻爲(x)*(∑c(i-1,k)*pow(9,i-1-k)(k∈(1,i-1)));
代碼如下:
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
using namespace std;
int jiu[10];
int jiecheng[10];
int a[10];
int c[10][10];
void dabiao()
{
for(int i=0;i<10;i++)//把9的多少次方打表,乘9乘9乘9就不用一個一個算了
{
jiu[i]=pow(9,i);
}
jiecheng[0]=1;
jiecheng[1]=1;
for(int i=2;i<10;i++)//階乘打表,爲下面的c(n,m)所用
{
jiecheng[i]=jiecheng[i-1]*i;
}
for(int i=1;i<10;i++)//題目說最多是999999999,共9位數,那麼我們公式中最多用到c(8,8)
{
for(int j=1;j<=i;j++)
{
c[i][j]=jiecheng[i]/(jiecheng[i-j]*jiecheng[j]);//排列組合公式
}
}
}
int he(int di)
{
int q=0;
for(int i=1;i<=di;i++)
{
q=q+c[di][i]*jiu[di-i];
}
return q;
}
int calc(int x)
{
int shu=a[x];
if(shu<4)
{
return shu*he(x-1);//公式
}
else
{
return (shu-1)*he(x-1)+pow(10,x-1);//公式
}
}
int main()
{
int n;
dabiao();
while(scanf("%d",&n)!=EOF)
{
if(n==0)
{
break;
}
int cnt=1;
int tmp=n;
while(tmp)//分解這個數到數組
{
a[cnt++]=tmp%10;
tmp=tmp/10;
}
int ans=0;
for(int i=cnt-1;i>=1;i--)//對每一位數的貢獻進行計算
{
ans=ans+calc(i);
}
printf("%d: %d\n",n,n-ans);//算出的是含四的數的個數,記得用n減去它
}
return 0;
}