51nod 1230 幸运数

题目大意

如果一个数各个数位上的数字之和是质数,并且各个数位上的数字的平方和也是质数,则称它为幸运数。
例如:120是幸运数,因为120的数字之和为3,平方和为5,均为质数,所以120是一个幸运数字。
给定x,y,求x,y之间( 包含x,y,即闭区间[x,y])有多少个幸运数。
 

Input

第1行:一个数T,表示后面用作输入测试的数的数量。(1 <= T <= 10000)
第2 - T + 1行:每行2个数,X, Y中间用空格分割。(1 <= X <= Y <= 10^18)

Output

输出共T行,对应区间中幸运数的数量。

Input示例

2
1 20
120 130

Output示例

4
1|

Solution

这一题显然可以这状态为dp[pos][sum][sum1][0/1]经典的数位dp,pos到第pos位

sum数位和maxsum=9*18,sum1平方和maxsum1=9*9*18,状态很少,但0/1不能

传递,所以每次只用重新算压在lim上的数的方案数就行了。记忆化搜索即可。

Code

 1 #include<cstdio>
 2 #include<cmath>
 3 #include<cstring>
 4 #include<algorithm>
 5 #define fo(i,a,b) for(int i=a;i<=b;i++)
 6 #define fd(i,a,b) for(int i=a;i>=b;i--)
 7 #define fh(i,x) for(int i=head[x];i;i=next[i])
 8 typedef long long LL;
 9 inline int max(int x,int y) {return (x<y)?y:x;}
10 inline int min(int x,int y) {return (x<y)?x:y;}
11 inline LL read() {
12     LL x=0,f=1;char ch=getchar();
13     while(ch<'0'||ch>'9') f=(ch=='-')?-1:f,ch=getchar();
14     while(ch>='0'&&ch<='9') x=x*10+(ch-'0'),ch=getchar();return f*x;
15 }
16 const int N=2e3+50,MAXN=2e3;
17 int prime[N],tot;
18 LL dp[20][200][N],dig[20];
19 bool isprime[N];
20 void init() {
21     memset(dp,-1,sizeof(dp));
22     memset(isprime,1,sizeof(isprime));
23     isprime[1]=false;
24     for(int i=2;i<=MAXN;i++) {
25         if(isprime[i])prime[++tot]=i;
26         for(int j=1;j<=tot&&i*prime[j]<=MAXN;j++) {
27             isprime[i*prime[j]]=false;
28             if(i%prime[j]==0)break;
29         }
30     }
31 }
32 LL dfs(int pos,int sum,int sum1,bool flag) {
33     if(pos<1) return (isprime[sum]&&isprime[sum1]);
34     if(!flag&&dp[pos][sum][sum1]!=-1) return dp[pos][sum][sum1];
35     int lim=(flag)?dig[pos]:9;
36     LL res=0;
37     fo(i,0,lim) res+=dfs(pos-1,sum+i,sum1+i*i,flag&&(i==lim));
38     if(!flag) dp[pos][sum][sum1]=res;
39     return res;
40 }
41 LL solve(LL x) {
42     int len=0;
43     while(x) dig[++len]=x%10,x=x/10;
44     return dfs(len,0,0,1);
45 }
46 int main() {
48     init();
49     int T=read();
50     while(T--) {
51         LL x=read(),y=read();
52         printf("%lld
",solve(y)-solve(x-1));
53     }
54     return 0;
55 }
原文地址:https://www.cnblogs.com/patricksu/p/7868609.html