51nod 1232:完美数

51nod 1232:完美数

题目链接:http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1232

题目大意:如果一个数能够被组成它的各个非$0$数字整除,则称它是完美数。例如:$10$,$11$,$12$,$101$都是完美数,但是$13$就不是完美数(因为$13$不能被数字3整除)。现在给定正整数$x$,$y$,求$[x,y]$中共有多少完美数。共有$T$组数据。

数位DP
如果对于$a \equiv r(mod m)$,存在$p|m$,则有$a \equiv r(mod p)$.
故我们可以记录被$2520$($lcm(1,2,3,4,5,6,7,8,9)$)模的余,代替分别记录被$1,2,3,4,5,6,7,8,9$模的余.
而标识$n$中含哪些数有多种方法:可以记录$lcm(p_i)$(此种需将$2520$的因子离散化),也可以用多个bool类型标记.
由于这道题$T$过大,故递推的方法不可行,采用记忆化搜索.
代码如下:
 1 #include <cstdio>
 2 #include <iostream>
 3 #include <cstring>
 4 #include <algorithm>
 5 #define N 20
 6 using namespace std;
 7 typedef long long ll;
 8 const int m=2520;
 9 int T,dig[N];
10 ll a,b,dp[N][50][2520],f[2525],g[50],mod[20];
11 int gcd(int a,int b){
12     return b==0?a:gcd(b,a%b);
13 }
14 int lcm(int a,int b){
15     return a/gcd(a,b)*b;
16 }
17 ll dfs(int pos,int fact,int r,bool limit){
18     if (pos<0) return r%g[fact]==0;
19     if (!limit&&dp[pos][fact][r]!=-1) return dp[pos][fact][r];
20     ll res=0;
21     int last=limit?dig[pos]:9;
22     for (int i=0;i<=last;i++){
23         int x=g[fact];
24         if(i>1)x=lcm(x,i);
25         res+=dfs(pos-1,f[x],(r+mod[pos]*i)%m,limit&&(i==last));
26     }
27     if (!limit) dp[pos][fact][r]=res;
28     return res;
29 }
30 ll solve(ll n){
31     int len=0;
32     while (n){
33         dig[len++]=n%10;
34         n/=10;
35     }
36     return dfs(len-1,0,0,1);
37 }
38 void init(){
39     int k=0,i;
40     memset(dp,-1,sizeof(dp));
41     for(i=1;i*i<m;++i)if(m%i==0){
42         g[k++]=i;
43         g[k++]=m/i;
44     }
45     if(i*i==m)g[k++]=i;
46     sort(g,g+k);
47     for(int i=0;i<k;++i)f[g[i]]=i;
48     for(int i=0,t=1;i<=18;++i,t=(t*10)%m)mod[i]=t;
49 }
50 int main(void){
51     init();
52     scanf("%d",&T);
53     while(T--){
54         scanf("%lld%lld",&a,&b);
55         printf("%lld\n",solve(b)-solve(a-1));
56     }
57 }

 

转载于:https://www.cnblogs.com/barrier/p/6724064.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
提供的源码资源涵盖了安卓应用、小程序、Python应用和Java应用等多个领域,每个领域都包含了丰富的实例和项目。这些源码都是基于各自平台的最新技术和标准编写,确保了在对应环境下能够无缝运行。同时,源码中配备了详细的注释和文档,帮助用户快速理解代码结构和实现逻辑。 适用人群: 这些源码资源特别适合大学生群体。无论你是计算机相关专业的学生,还是对其他领域编程感兴趣的学生,这些资源都能为你提供宝贵的学习和实践机会。通过学习和运行这些源码,你可以掌握各平台开发的基础知识,提升编程能力和项目实战经验。 使用场景及目标: 在学习阶段,你可以利用这些源码资源进行课程实践、课外项目或毕业设计。通过分析和运行源码,你将深入了解各平台开发的技术细节和最佳实践,逐步培养起自己的项目开发和问题解决能力。此外,在求职或创业过程中,具备跨平台开发能力的大学生将更具竞争力。 其他说明: 为了确保源码资源的可运行性和易用性,特别注意了以下几点:首先,每份源码都提供了详细的运行环境和依赖说明,确保用户能够轻松搭建起开发环境;其次,源码中的注释和文档都非常完善,方便用户快速上手和理解代码;最后,我会定期更新这些源码资源,以适应各平台技术的最新发展和市场需求。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值