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\n",solve(y)-solve(x-1));
53     }
54     return 0;
55 }
时间: 2024-10-05 08:56:01

51nod 1230 幸运数的相关文章

51nod 1230:幸运数

51nod 1230:幸运数 题目链接:http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1230 题目大意:如果一个数各个数位上的数字之和是质数,并且各个数位上的数字的平方和也是质数,则称它为幸运数.例如:120是幸运数,因为120的数字之和为3,平方和为5,均为质数,所以120是一个幸运数字.给定x,y,求x,y之间( 包含x,y,即闭区间[x,y])有多少个幸运数. 数位DP 代码如下: 1 #include <cs

[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

【蓝桥杯】历届试题 幸运数

  历届试题 幸运数   时间限制:1.0s   内存限制:256.0MB 问题描述 幸运数是波兰数学家乌拉姆命名的.它采用与生成素数类似的“筛法”生成. 首先从1开始写出自然数1,2,3,4,5,6,.... 1 就是第一个幸运数. 我们从2这个数开始.把所有序号能被2整除的项删除,变为: 1 _ 3 _ 5 _ 7 _ 9 .... 把它们缩紧,重新记序,为: 1 3 5 7 9 .... .这时,3为第2个幸运数,然后把所有能被3整除的序号位置的数删去.注意,是序号位置,不是那个数本身能否

蓝桥杯 - 幸运数 (打表)

历届试题 幸运数 时间限制:1.0s   内存限制:256.0MB 问题描述 幸运数是波兰数学家乌拉姆命名的.它采用与生成素数类似的"筛法"生成 . 首先从1开始写出自然数1,2,3,4,5,6,.... 1 就是第一个幸运数. 我们从2这个数开始.把所有序号能被2整除的项删除,变为: 1 _ 3 _ 5 _ 7 _ 9 .... 把它们缩紧,重新记序,为: 1 3 5 7 9 .... .这时,3为第2个幸运数,然后把所有能被3整除的序号位置的数删去.注意,是序号位置,不是那个数本身

51nod 1043 幸运号码(数位dp)

题目链接:51nod 1043 幸运号码 题解:dp[i][j]表示 i 个数和为 j 的总数(包含0开头情况) dp[i][j] = dp[i-1][j-k] i & 1 :这里用滚动数组节省内存 非0开头的情况 * 0开头的情况:(dp[n&1][i]-dp[(n-1)&1][i]) *dp[n&1][i],最后将其累加即为结果. 1 #include<cstdio> 2 #include<algorithm> 3 #include<cst

幸运数的各位和[Codeforces-109A]

Codeforces Beta Round #84 (Div. 1 Only)  时间限制2000ms,内存限制256MB 问题大意:定义幸运数为十进制表示只包含4.7两个数码的数.例如47.744.4都是幸运数,而5.17.467不是. 已知一个幸运数的各位之和,求满足条件的幸运数的最小值.输入保证$1≤n≤10^6$. 这题用暴力方法就可以做.需要注意题目中的几个信息: 1)输入可能达到$10^6$,因此原数必然超过$10^6÷9>10^5$,因此无论用32位还是64位整数是不可能表示的下的

曦皓的幸运数

[题目描述] 仅包含4或7的数被称为幸运数. 一个序列的子序列被定义为从序列中删去若干个数,剩下的数组成的新序列.两个子序列被定义为不同的当且仅当其中的元素在原始序列中的下标的集合不相等.对于一个长度为N的序列,共有2^N个不同的子序列(包含一个空序列). 一个子序列被称为不幸运的,当且仅当其中不包含两个相同的幸运数. 对于一个给定序列,求其中长度恰好为K的不幸运子序列的个数,答案 mod (10^9+7)输出. [输入描述] 第一行两个正整数N.K,表示原始序列的长度和题目中的K: 接下来一行

京东笔试之幸运数问题:4,7

题目描述 4和7是两个幸运数字,我们定义,十进制表示中,每一位只有4和7两个数的正整数都是幸运数字. 前几个幸运数字为:4,7,44,47,74,77,444,447... 现在输入一个数字K,输出第K个幸运数. 输入 第一行一个数字T(T<=1000)表示测试数据的组数.对于每组测试数据,输出一个数K 输出 每组数据输出一行,第K个幸运数. 样例输入 351001000000000 样例输出 74744747 77477744774747744747444444447 思路 首先把4和7化为0

幸运数

文字描述:将队列法所描述得序列拿来比较会发现一个规律,如下:初始序列: 4 , 7 4,7 得序列2: 44 , 47 , 74 , 77 得序列3: 444 , 447 , 474 , 477 , 744 , 747 , 774 , 777 规律:每个序列是包含当前位数得所有幸运数,而且相较前一个序列是以2的倍数递增,每个序列得前一半以 4 开头,后一半是以 7 开头,当把头位去掉以后,剩下得幸运数正好是上一个序列,例如序列3包含所有位数为 3 3 得幸运数,而且前 4 个幸运数是以 4 开头