[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
", f(r)-f(l-1));
59   }
60   return 0;
61 }
原文地址:https://www.cnblogs.com/kirai/p/5996063.html