1. 程式人生 > >51nod 1232 完美數

51nod 1232 完美數

print mat lap space long long new sizeof eof con

題目思路:數位dp,若這個數能被每位的非0數整除,那麽這個數一定可以被每一位數的lcm整除,lcm(1,2,3,4,5,6,7,8,9) = 2520,所以可以通過將這個數對2520取模來壓縮空間,取模結果計做mod

dp[pos][lcm][mod],顯然20*2520*2520仍然過大,所以我們對mod進行離散,再次壓縮空間。

技術分享
#include <iostream>
#include <cmath>
#include <string.h>
#include <cstdio>
#include <queue>
#include 
<algorithm> using namespace std; #define LL long long #define MAXSIZE 2600 #define INF 0x3f3f3f3f LL dp[20][50][MAXSIZE]; const LL Mod = 2520; int bit[MAXSIZE],ha[MAXSIZE]; LL gcd(LL n,LL m) { if(n%m == 0) return m; return gcd(m,n%m); } void Init() { int pos = 1
; for(int i=1;i<=Mod;i++) { if(2520%i == 0) ha[i] = pos++; } } LL dfs(int pos,int lcm,int mod,int limit) { if(pos < 0) { if(mod%lcm == 0) return 1; return 0; } if(dp[pos][ha[lcm]][mod] != -1 && !limit)
return dp[pos][ha[lcm]][mod]; LL ans = 0; int len = limit?bit[pos]:9; for(int i=0;i<=len;i++) { if(i != 0) { int new_lcm = lcm*i/(gcd(lcm,i)); int num = (mod*10+i)%Mod; ans += dfs(pos-1,new_lcm,num,limit&&i==len); } else { int num = mod*10%Mod; ans += dfs(pos-1,lcm,num,limit&&i==len); } } if(!limit) dp[pos][ha[lcm]][mod] = ans; return ans; } LL Solve(LL n) { int pos = 0; while(n) { bit[pos++] = n%10; n /= 10; } LL ans = dfs(pos-1,1,0,1); return ans; } int main() { Init(); int T; LL n,m; scanf("%d",&T); memset(dp,-1,sizeof(dp)); while(T--) { scanf("%lld%lld",&n,&m); LL ans = Solve(m) - Solve(n-1); printf("%lld\n",ans); } return 0; }
View Code

51nod 1232 完美數