显然我们只要知道1~x范围有多少幸运数(用f(x)表示),lucky(x,y)=f(y)-f(x-1).

解法1. 计算排列数

由于y<=1000000000这个规模,我们不能暴力验证每个数是否是幸运数。可以想到,对于同样的数字组成,不同的数字排列对应不同的幸运数,比如12,21。那么就只需枚举合法的数字组成,算出相应的排列数。设数字i有a[i]个,n=Σa[i],则对应的排列数是n!/∏a[i]!。

接下来就只要枚举那些合法的数字组成了。我们希望枚举时对每位的可取数字是没有限制的,可以分类来进行。下面举例说明。

比如x=2345. 当千位是0或1时,后三位是没有限制的,0~9都可以,可以用递归来枚举a[i],然后结合已确定的千位来判断这种组成是否是幸运数,是的话答案就加上相应的排列数。

当千位等于2时,继续依次固定百位=0,1,2计算。余此类推。

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<time.h>
using namespace std; bool isPrime(int n)
{
if(n<2) return false;
int i;
for(i=2;i*i<=n;i++) if(n%i==0) return false;
return true;
} bool check(int cnt[],int n1,int n2)
{
int i;
int s1=n1,s2=n2;
for(i=1;i<10;i++)
{
s1+=i*cnt[i];
s2+=i*i*cnt[i];
}
return isPrime(s1)&&isPrime(s2);
} int fac[10];
void comFactorial()
{
int i;
fac[0]=1;
for(i=1;i<10;i++) fac[i]=fac[i-1]*i;
} int nPermutation(int cnt[])
{
int i;
int n=0;
for(i=0;i<10;i++) n+=cnt[i];
int ans=fac[n];
for(i=0;i<10;i++) ans/=fac[cnt[i]];
return ans;
} void dfs(int digit,int n,int cnt[],int n1,int n2,int &ans)
{
int i;
if(digit==10)
{
cnt[0]=n;
if(check(cnt,n1,n2))
ans+=nPermutation(cnt);
return ;
}
for(i=0;i<=n;i++)
{
cnt[digit]=i;
dfs(digit+1,n-i,cnt,n1,n2,ans);
}
} int com(int x)
{
comFactorial();
int digit[12];
int cnt[12];
int i,j,n=0;
while(x>0)
{
digit[n++]=x%10;
x/=10;
}
int n1=0,n2=0,s1,s2,ans=0;
for(i=n-1;i>0;i--)
{
for(j=0;j<digit[i];j++)
{
s1=n1+j;
s2=n2+j*j;
dfs(1,i,cnt,s1,s2,ans);
}
n1+=digit[i];
n2+=digit[i]*digit[i];
}
for(i=0;i<=digit[0];i++)
{
s1=n1+i;
s2=n2+i*i;
if(isPrime(s1)&&isPrime(s2)) ans++;
}
return ans;
} int lucky(int x,int y)
{
return com(y)-com(x-1);
}

  

解法2. dp

dp[n][s1][s2]表示n位,各位数字的和为s1,平方和为s2的方法数。根据第一位的数字来状态转移,dp[n][s1][s2]=Σdp[n-1][s1-i][s2-i*i] i=0...9

两种方法的共同之处是都要逐渐固定高位来分类计算。

#include <cstring>
#include <vector>
#include <iostream>
#include <set>
#include <map>
#include <algorithm>
#include<deque>
#include<cstdio>
#include<time.h>
using namespace std; int dp[12][82][730]; bool isPrime(int n)
{
int i;
if(n<2) return false;
for(i=2;i*i<=n;i++) if(n%i==0) return false;
return true;
} int f(int n,int s1,int s2)
{
if(dp[n][s1][s2]!=-1) return dp[n][s1][s2];
if(n==1)
{
if(s1<10&&s1*s1==s2) return dp[n][s1][s2]=1;
else return dp[n][s1][s2]=0;
}
else
{
int i;
int ans=0;
for(i=0;i<10&&i<=s1&&i*i<=s2;i++) ans+=f(n-1,s1-i,s2-i*i);
return dp[n][s1][s2]=ans;
}
} int com(int x)
{
int a[20];
int num=0;
while(x>0)
{
a[num++]=x%10;
x/=10;
}
int ans=0;
int i,j,k,m;
int s1=0,s2=0;
int p1=0,p2=0;
for(k=num-1;k>0;k--)
{
for(m=0;m<a[k];m++)
{
s1=p1+m;
s2=p2+m*m;
for(i=0;i<=9*k;i++)
for(j=i;j<=81*k;j++)
{
if(isPrime(i+s1)&&isPrime(j+s2))
ans+=f(k,i,j);
}
}
p1+=a[k];
p2+=a[k]*a[k];
}
for(i=0;i<=a[0];i++)
if(isPrime(p1+i)&&isPrime(i*i+p2)) ans++;
return ans;
} int lucky(int x,int y)
{
memset(dp,-1,sizeof(dp));
return com(y)-com(x-1);
}

  

转自 http://blog.csdn.net/shuyechengying/article/details/9164517

pongo英雄会-幸运数题解的更多相关文章

  1. [COJ0528]BJOI幸运数

    [COJ0528]BJOI幸运数 试题描述 输入 见"试题描述" 输出 见"试题描述" 输入示例 见"试题描述" 输出示例 见"试 ...

  2. Problem 1007 幸运数 线段树成段更新

    题目链接: 题目 Problem 1007 幸运数 Time Limit: 2000 mSec Memory Limit : 131072 KB 问题描述 皮特的幸运数是2和5.只由幸运数字2和5组成 ...

  3. 蓝桥杯  历届试题 幸运数  dfs

    历届试题 幸运数 时间限制:1.0s   内存限制:256.0MB 问题描述 幸运数是波兰数学家乌拉姆命名的.它采用与生成素数类似的"筛法"生成 . 首先从1开始写出自然数1,2, ...

  4. 京东2017校园招聘笔试题 【第K个幸运数】

    题目描述 4和7是两个幸运数字,我们定义,十进制表示中,每一位只有4和7两个数的正整数都是幸运数字. 前几个幸运数字为:4,7,44,47,74,77,444,447... 现在输入一个数字K,输出第 ...

  5. [51NOD1230]幸运数(数位DP)

    题目链接:http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1230 dp(l,s,ss)表示长度为l的数各位和为s,各位平方 ...

  6. C#版 - Leetcode 504. 七进制数 - 题解

    C#版 - Leetcode 504. 七进制数 - 题解 Leetcode 504. Base 7 在线提交: https://leetcode.com/problems/base-7/ 题目描述 ...

  7. C#版 - Leetcode 306. 累加数 - 题解

    版权声明: 本文为博主Bravo Yeung(知乎UserName同名)的原创文章,欲转载请先私信获博主允许,转载时请附上网址 http://blog.csdn.net/lzuacm. C#版 - L ...

  8. C#版(打败97.89%的提交) - Leetcode 202. 快乐数 - 题解

    版权声明: 本文为博主Bravo Yeung(知乎UserName同名)的原创文章,欲转载请先私信获博主允许,转载时请附上网址 http://blog.csdn.net/lzuacm. C#版 - L ...

  9. Python 计算当真因子个数为偶数个时为幸运数,计算区间内幸运数之和

    晚饭后朋友发来个问题,正好无事做,动手写了一下 若一个正整数有偶数个不同的真因子,则称该数为幸运数.如4含有2个真因子为 1 和 2 .故4是幸运数.求[2,100]之间的全部幸运数之和. 常规思路 ...

随机推荐

  1. XMind与MindManager哪个好(网易云课堂老师:Array老师讲解稿)

    XMind与MindManager哪个好 作者:网易云课堂老师:Array老师讲解稿 思维导图是一种将放射性思考具体化的方法,可以将人们的创造性思维及时捕捉并呈现,深受商业人士的喜爱.目前,XMind ...

  2. [转]Java中的随机数生成器:Random,ThreadLocalRandom,SecureRandom

     详见: http://blog.yemou.net/article/query/info/tytfjhfascvhzxcytp84 Random即:java.util.Random, ThreadL ...

  3. 【C# in depth 第三版】温故而知新(1)

    声明 本文欢迎转载,原文地址:http://www.cnblogs.com/DjlNet/p/7192354.html 前言 关于这本书(<深入理解C# 第三版>)的详细情况以及好坏,自行 ...

  4. Qt--自定义Model

    众所周知,Qt提供了一套Model/View框架供开发者使用,Model用来提供数据, View则用来提供视觉层的显示.实际上这是一套遵循MVC设计模式的GUI框架,因为Qt还提供了默认的Delega ...

  5. jquery 函数大全

    jquery函数大全转载  Attribute:$(”p”).addClass(css中定义的样式类型); 给某个元素添加样式$(”img”).attr({src:”test.jpg”,alt:”te ...

  6. 姑娘你大胆地往前走——答大二学生XCL之八问

    姑娘你大胆地往前走--答大二学生XCL之八问 以下问题的答案写给我家正在读大二的XCL. 写于 2017-9-13 晚 请问您是为什么选择了IT行业的? 与其说是我选择了行业,不如说是行业选择了我. ...

  7. 201521123009 《Java程序设计》第7周学习总结

    1. 本周学习总结 2. 书面作业 Q1:ArrayList代码分析 1.1 解释ArrayList的contains源代码 //contains()方法 public boolean contain ...

  8. 201521123070 《JAVA程序设计》第5周学习总结

    1. 本章学习总结 1.1 尝试使用思维导图总结有关多态与接口的知识点. http://naotu.baidu.com/file/02b01f465e125c5942648a03358273b0 2. ...

  9. 201521123064 《Java程序设计》第13周学习总结

    本次作业参考文件 正则表达式参考资料 1. 本章学习总结 1.1 以你喜欢的方式(思维导图.OneNote或其他)归纳总结多网络相关内容. ① InetAddress(IP地址对应的类) InetAd ...

  10. 201521123068 《java程序设计》 第10周学习总结

    1. 本周学习总结 1.1 以你喜欢的方式(思维导图或其他)归纳总结异常与多线程相关内容. 2. 书面作业 本次PTA作业题集异常.多线程 1.finally 题目4-2 1.1 截图你的提交结果(出 ...