显然我们只要知道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. spring mvc:注解@ModelAttribute妙用

    在Spring mvc中,注解@ModelAttribute是一个非常常用的注解,其功能主要在两方面: 运用在参数上,会将客户端传递过来的参数按名称注入到指定对象中,并且会将这个对象自动加入Model ...

  2. 南昌招聘.net开发大牛

    职位诱惑: 12年名企5险1金齐全+WEB&移动研发=丰厚回报 职位描述: 聘精通web开发成员共同成就事业! 中国领先的WEB内核 研发机构.华中地区唯一自主CMS研发厂商.江西最大的网站服 ...

  3. poj 1149经典网络流构图

    题意:m个猪圈,n个客户,每个客户给出选则猪圈的钥匙和需要购买猪的个数,其中每次客户购买时客户选则的猪圈数量可以相互更换,问最大购买数量. 思路:以客户作为除源点汇点之外的点,然后对于每个猪圈从源点连 ...

  4. Excel表单的读取与处理 PHPExcel与Apache POI

    近日,连续遇到需要对Excel表单内容进行读取的需求.一个是在php环境下,一个是在java环境下.这里简要记录这两种环境,利用第三方提供的函数库对Excel进行处理的方法. d0710 : Fini ...

  5. 转:【Java并发编程】之九:死锁(含代码)

    转载请注明出处:http://blog.csdn.net/ns_code/article/details/17200937 当线程需要同时持有多个锁时,有可能产生死锁.考虑如下情形: 线程A当前持有互 ...

  6. 转:【Java集合源码剖析】LinkedHashmap源码剖析

    转载请注明出处:http://blog.csdn.net/ns_code/article/details/37867985   前言:有网友建议分析下LinkedHashMap的源码,于是花了一晚上时 ...

  7. 【Alpha】 第七次Daily Scrum Meeting

    一.本次会议为第七次meeting会议 二.时间:9:37AM-9:50AM 地点:禹州三楼 三.会议站立式照片 四.今日任务 成员 昨日任务 今日任务 林清青 学习并了解微信程序相关方面知识,为小组 ...

  8. 【Alpha】——Fifth Scrum Meeting

    一.今日站立式会议照片 二.每个人的工作 成员 昨天已完成的工作 今天计划完成的工作 李永豪 测试统计功能 对统计出现的问题进一步完善 郑靖涛 着手编写报表设计 继续报表设计 杨海亮 协助编写统计功能 ...

  9. 201521123104 《Java程序设计》第6周学习总结

    1. 本周学习总结 1.1 面向对象学习暂告一段落,请使用思维导图,以封装.继承.多态为核心概念画一张思维导图,对面向对象思想进行一个总结. 2. 书面作业 1. clone方法 1.1 Object ...

  10. 201521123062《Java程序设计》第5周学习总结

    1. 本周学习总结 1.1 尝试使用思维导图总结有关多态与接口的知识点. 1.2 可选:使用常规方法总结其他上课内容. 2. 书面作业 1.代码阅读:Child压缩包内源代码 1.1 com.pare ...