[51NOD1230]幸运数(数位DP)
题目链接:http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1230
dp(l,s,ss)表示长度为l的数各位和为s,各位平方和为ss的幸运数的个数。
1 #include <bits/stdc++.h> 2 #pragma comment(linker, "/STACK:10240000,10240000") 3 using namespace std; 4 5 typedef long long LL; 6 const int maxn = 22; 7 const int maxa = 162; 8 const int maxm = 1610; 9 LL l, r; 10 LL dp[maxn][maxa][maxm]; 11 int digit[maxn]; 12 bool isprime[maxm]; 13 14 void printlist() { 15 memset(isprime, true, sizeof(isprime)); 16 isprime[0] = isprime[1] = false; 17 int pedge = int(sqrt(maxm)); 18 for(int i = 2; i <= pedge; i++) { 19 if(isprime[i]) { 20 int o = maxm / i; 21 for(int j = 2; j <= o; j++) { 22 isprime[i*j] = false; 23 } 24 } 25 } 26 } 27 28 LL dfs(int l, int s, int ss, bool flag) { 29 if(l == 0) return isprime[s] && isprime[ss]; 30 if(!flag && ~dp[l][s][ss]) return dp[l][s][ss]; 31 int pos = flag ? digit[l] : 9; 32 LL ret = 0; 33 for(int i = 0; i <= pos; i++) { 34 ret += dfs(l-1, s+i, ss+i*i, flag&&(pos==i)); 35 } 36 if(!flag) dp[l][s][ss] = ret; 37 return ret; 38 } 39 40 LL f(LL x) { 41 if(x < 0) return 0; 42 int pos = 0; 43 while(x) { 44 digit[++pos] = x % 10; 45 x /= 10; 46 } 47 return dfs(pos, 0, 0, true); 48 } 49 50 int main() { 51 //freopen("in", "r", stdin); 52 printlist(); 53 memset(dp, -1, sizeof(dp)); 54 int T; 55 scanf("%d", &T); 56 while(T--) { 57 scanf("%lld%lld",&l,&r); 58 printf("%lld\n", f(r)-f(l-1)); 59 } 60 return 0; 61 }