題目大意:
給乙個數字n,範圍在1~2^63-1,求1~n之間含有49的數字有多少個。
思路:狀態轉移:
dp[i][0]代表長度為 i 並且不含有49的數字的個數;
dp[i][1]代表長度為 i 並且不含有49,但是最高位是9的數字的個數;
dp[i][2]代表長度為 i 並且含有49的數字的個數。
陣列 a[i] 從低位到高位儲存 n 的每一位數字。
則:dp[i][0] = dp[i-1][0] * a[i] - dp[i-1][1]; 表示長度為 i 的不含有49的數字的個數等於長度為 i - 1 的不含有49的數字的個數*當前的數字,因為這個位置可以填0~a[i] - 1,然後再減去長度為 i - 1 的最高位是9的數字的個數,因為如果長度為 i - 1 的最高位是9的話,那麼高一位就不能填4了,否則就組成了49。
dp[i][1] = dp[i-1][0]; 表示長度為 i 的並且不含有49同時最高位是9的數字的個數等於,長度為 i - 1 的不含有49的數字的個數,因為只要在它的高一位加上乙個9就可以了。
dp[i][2] = dp[i-1][2] * a[i] + dp[i-1][1]; 表示長度為 i 的含有49的數字的個數等於,長度為 i - 1 的數字的個數*當前的數字,再加上長度為 i - 1 的並且不含有49同時最高位是9的數字的個數,因為這個時候,只要在高一位加上乙個4就可以了,這樣在最高的兩位就組成了乙個49。
做法是從數字的高位向低位掃瞄,對於第 i 位,
首先加上長度為 i - 1 的符合條件的數字個數;
再討論以前是不是出現過49,如果出現過,就要再追加上長度為 i - 1 的不符合條件的數字的個數,因為以前已經有49了;
如果沒有出現過,就要判斷這一位是不是大於4呢,如果大於4,就要再追加上長度為 i - 1 的不含有49但是最高位是9的數字的個數,因為這個時候可以再這一位填4,因為它大於4嘛~;
然後就是判斷一下,當前位和上一位是不是滿足49,如果滿足,標記出現了49了!為以後的判斷做準備。
// dp[i][0] 表示在第i位時,不包含49的資料的個數。
// dp[i][1] 表示在第i位時,不包含49,但第i位為9的資料的個數。
// dp[i][2] 表示在第i位時,包含49的資料的個數。
#include #include #include #include #define ll long long
using namespace std;
ll dp[20][3];
int num[20]; //用來儲存n的每一位。
int main()
int t;
ll n;
cin >> t;
while(t--)
bool flag = false; //用來標記以前出現過49沒有
ll ans = 0,last = 0;
for (int i = len ;i >= 1;--i)
if (flag == 0 && num[i] > 4)
if (last == 4 && num[i] == 9)
last = num[i];
}printf("%lld\n",ans );
}return 0;
}
hdu 3555 數字dp入門
題意 給定乙個long long型別能夠存下的數字n,統計1 n之間含有49的數字的個數 思路 初始版本 需要記錄當前位置,前一位置放了那個數字,當前是否已經包含49,是否有上界這四個資訊,也就是dfs的四個引數。dfs pos,pre,istrue,limit 其實這種做法有點相當於把普通的數字d...
hdu 3555數字DP 入門題
include include include include include include include include include include includeusing namespace std typedef long long ll define inf 0x3f3f3f3f ...
數字dp入門題hdu 3555
題意就是簡單的給定乙個n求1 n所有含有49的數字 數字dp入門題可以當作模板改。pos表示到pos位,pre為上一位的數字用來判斷是否可以得到49,sta表示狀態,無非就是如果該為是4的時候和不是4的時候,對下一位dp的影響。limit表示是否到了限制如213則百位是2則十位只能為0,1。這題網上...