【HDU - 5456】Matches Puzzle Game(数位dp,思维)
題干:
As an exciting puzzle game for kids and girlfriends, the Matches Puzzle Game asks the player to find the number of possible equations?A?B=CA?B=C?with exactly?n?(5≤n≤500)n?(5≤n≤500)?matches (or sticks).?
In these equations,?A,BA,B?and?CC?are positive integers. The equality sign needs two matches and the sign of subtraction needs just one. Leading zeros are not allowed.?
Please answer the number, modulo a given integer?m?(3≤m≤2×109)m?(3≤m≤2×109).?
Input
The input contains several test cases. The first line of the input is a single integer?tt?which is the number of test cases. Then?t?(1≤t≤30)t?(1≤t≤30)?test cases follow.?
Each test case contains one line with two integers?n?(5≤n≤500)n?(5≤n≤500)?and?m?(3≤m≤2×109)m?(3≤m≤2×109).
Output
For each test case, you should output the answer modulo?mm.?
Sample Input
4 12 1000000007 17 1000000007 20 1000000007 147 1000000007Sample Output
Case #1: 1 Case #2: 5 Case #3: 38 Case #4: 815630825解題報(bào)告:
? ?一眼上來(lái)就是搜索,誰(shuí)能想到是數(shù)位dp、、太難了太難了、、
首先去掉3根火柴棒來(lái)湊成減號(hào)和等號(hào),然后問(wèn)題就變成了將剩下的火柴棒拼成B+C=A的形式。然后同時(shí)對(duì)ABC這三個(gè)數(shù)的同一個(gè)數(shù)位進(jìn)行dp,注意這題dp的時(shí)候不是跟一般的數(shù)位dp一樣是從高位到低位進(jìn)行dp的,而是從低位像高位進(jìn)行dp,因?yàn)檫@樣方便記錄前導(dǎo)零的問(wèn)題。
參考題解,用dp[n][a][b][c]來(lái)表示剩余n根火柴棒時(shí),從最低位開始的放法總數(shù),a表示當(dāng)前位是否有來(lái)自低一位的進(jìn)位,b表示是否已停止放B這個(gè)數(shù),c表示是否已停止放C這個(gè)數(shù),則最終我們所求的結(jié)果就是dp[n-3][0][0][0]。
代碼邏輯是這樣的:
num[i]代表要湊出i這個(gè)數(shù)字需要的火柴個(gè)數(shù)。
每次檢查當(dāng)前剩余多少根火柴,如果<0直接return 0,然后如果b和c都已經(jīng)停止了,那么直接進(jìn)入出口,當(dāng)然,出口中返回0或者1要檢查是否合法:如果當(dāng)前沒(méi)有來(lái)自低一位的進(jìn)位(又因?yàn)锽和C已經(jīng)停止了),所以你當(dāng)前位也肯定是啥都沒(méi)有,也就是要檢查cnt是否=0;如果有來(lái)自低一位的進(jìn)位,那么當(dāng)前位一定是1,也就是看cnt是否==num[1]就行了。
然后就是枚舉中間過(guò)程,注意這里只是用了數(shù)位dp的思想,所以不需要設(shè)置limit啥之類的東西,并且之類的res需要設(shè)置成longlong不然就爆int了。
然后就是分b和c這幾種情況進(jìn)行討論,如果B和C都還沒(méi)確定,那么就枚舉他們分別取值是什么,然后通過(guò)B和C的取值就得到A對(duì)應(yīng)位的取值(不難證明 一定是(B+C)%10,并且如果有進(jìn)位,那么進(jìn)位一定是1,可以通過(guò)小學(xué)學(xué)習(xí)的加法豎式簡(jiǎn)單證明)。
枚舉好B和C之后,就有幾種選擇,可以讓B停止,可以讓C停止,也可以讓B和C都停止,分別進(jìn)行討論就行了。注意B能停止的話,一定要保證i>0,同理C能停止的話,一定要保證j>0,因?yàn)椴蝗痪蜁?huì)出現(xiàn)前導(dǎo)零的情況使得這樣就會(huì)出現(xiàn)前導(dǎo)零的情況,所以我們要避免這種情況發(fā)生,所以我沒(méi)要特判一下i是否等于0,來(lái)進(jìn)行下一步判斷就可以了,其他的情況同理,就不再說(shuō)了。
AC代碼:
#include<cstdio> #include<iostream> #include<algorithm> #include<queue> #include<map> #include<vector> #include<set> #include<string> #include<cmath> #include<cstring> #define F first #define S second #define ll long long #define pb push_back #define pm make_pair using namespace std; typedef pair<int,int> PII; const int MAX = 555 + 5; int t,iCase,n; const int num[]= {6,2,5,5,4,5,6,3,7,6}; ll mod; ll dp[555][2][2][2]; ll dfs(int cnt,int a,int b,int c) {if(cnt<0)return 0;if(~dp[cnt][a][b][c])return dp[cnt][a][b][c];if(b&&c) {if((a&&cnt==num[1])||(!a&&!cnt))return 1;else return 0;}ll res = 0;if(!b&&!c) {for(int i=0; i<=9; ++i)for(int j=0; j<=9; ++j) {res+=dfs(cnt-(num[i]+num[j]+num[(i+j+a)%10]),(i+j+a)/10,0,0);if(i)res+=dfs(cnt-(num[i]+num[j]+num[(i+j+a)%10]),(i+j+a)/10,1,0);if(j)res+=dfs(cnt-(num[i]+num[j]+num[(i+j+a)%10]),(i+j+a)/10,0,1);if(i&&j)res+=dfs(cnt-(num[i]+num[j]+num[(i+j+a)%10]),(i+j+a)/10,1,1);}} else if(!b) {for(int i=0; i<=9; ++i) {res+=dfs(cnt-(num[i]+num[(i+a)%10]),(i+a)/10,0,1);if(i)res+=dfs(cnt-(num[i]+num[(i+a)%10]),(i+a)/10,1,1);}} else if(!c) {for(int i=0; i<=9; ++i) {res+=dfs(cnt-(num[i]+num[(i+a)%10]),(i+a)/10,1,0);if(i)res+=dfs(cnt-(num[i]+num[(i+a)%10]),(i+a)/10,1,1);}}dp[cnt][a][b][c] = res % mod;return dp[cnt][a][b][c]; } int main() {cin>>t;while(t--) {memset(dp,-1,sizeof dp);scanf("%d%lld",&n,&mod);ll ans = dfs(n-3,0,0,0)%mod;ans = (ans+mod)%mod;printf("Case #%d: %lld\n",++iCase,ans);}return 0 ; }?
總結(jié)
以上是生活随笔為你收集整理的【HDU - 5456】Matches Puzzle Game(数位dp,思维)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 【POJ - 1741】Tree(树分治
- 下一篇: 【牛客 - 370E】Rinne Lov