#10167. 「一本通 5.3 練習 2」不要 62
阿新 • • 發佈:2018-12-17
杭州人稱那些傻乎乎粘嗒嗒的人為 626262(音:laoer)。
杭州交通管理局經常會擴充一些的士車牌照,新近出來一個好訊息,以後上牌照,不再含有不吉利的數字了,這樣一來,就可以消除個別的士司機和乘客的心理障礙,更安全地服務大眾。
不吉利的數字為所有含有 444 或 626262 的號碼。例如:62315,73418,8891462315,73418,8891462315,73418,88914 都屬於不吉利號碼。但是,611526115261152 雖然含有 666 和 222,但不是 626262 連號,所以不屬於不吉利數字之列。
你的任務是,對於每次給出的一個牌照區間號,推斷出交管局今後又要實際上給多少輛新的士車上牌照了。
【輸入格式】
輸入的都是整數對 n,mn,mn,m,如果遇到都是 000 的整數對,則輸入結束。
【輸出格式】
對於每個整數對,輸出一個不含有不吉利數字的統計個數,該數值佔一行位置。
【樣例輸入】
1 100
0 0
【樣例輸出】
80
【資料範圍與提示】
對於全部資料,0<n≤m<1070\lt n\le m\lt 10^70<n≤m<107。
思路:我真的不想說了
就一句話:一位一位模擬
不懂的話就直接看程式碼吧,我解釋的很清楚了
#include<cstdio> #include<cstring> #include<algorithm> using namespace std; #define ll long long ll f[2100][2100];//f[i][j]表示以i為最高位的j位數的吉利數字有多少個 ll x,y; ll a[2100],len;//len表示當前這個數的最高位,a陣列是記錄數位的 void dfs() { for(int i=0;i<=9;i++) if(i!=4) f[i][1]=1;//一位數的情況,只要不為4,這種情況就是成立的 for(int i=2;i<=10;i++)//數位的迴圈(2^31是十位數) { for(int j=0;j<=9;j++) if(j!=4)//從當前的最高位開始迴圈 { for(int k=0;k<=9;k++) if(k!=4 && (j!=6 || k!=2))//次高位,只要不是4或者最高位和次高位聯合起來不是62就可以 { f[j][i]+=f[k][i-1];//當前的以j為最高位的i位數 繼承的是 以次高位的k為最高位的i-1位數的狀態(當前是i位,前一個就是i-1) } } } } ll solve(int t)//尋找合適的數 //t表示當前要計算的是 //用函式表示是為了程式碼的簡潔,不用x計算一次,y又計算一次 { ll sum=0;//記錄答案 len=0;//數位最開始要初始化(注意:不能為了方便在上面將len初始化,這樣每一次計算就會歸0) if(t==0) return 1; while(t>0) { a[++len]=t%10; t/=10; }//分離數位儲存在a數組裡面 a[len+1]=0;//a陣列也要初始化,不用擔心會計算不了,因為a[++len]會覆蓋 for(int i=len;i>=1;i--)//從當前這個數的最高位開始迴圈,i表示的是位數 { for(int j=0;j<a[i];j++)//保證不會超出範圍 //j就是第i位數的數字 //比如說,如果是4321,a[i]=4,那麼j就表示 0~3999,如果=a[i]就是0~4999 就超出了要求的數的範圍了 { if(j!=4 && (a[i+1]!=6 || j!=2)) sum+=f[j][i]; //當前這一位a[i]也可以表示為j不是4就可以繼續判斷, //而且,當前這一位的上一位的數字不能為6,而且當前這一位a[i]也可以表示為j的不是2就不能湊出62,就是成立的 } if(a[i]==4 || (a[i]==2 && a[i+1]==6)) break; //如果迴圈到這個數的某一位是4,或者當前的某一位和前面一位是62,就退出,因為不符合條件 if(i==1) sum++;//如果一直迴圈到最後一位,就是一位數仍然成立,就記錄這一種答案 } return sum; } int main() { dfs(); while(scanf("%lld%lld",&x,&y)!=EOF) { if(x==0 && y==0) break;//如果x==0 並且 y==0,就沒有成立的,不輸出答案,直接退出 printf("%lld\n",solve(y)-solve(x-1)); } return 0; }