TOJ 2294 POJ 3286 How many 0's? 数位dp

http://acm.tju.edu.cn/toj/showp2294.html

http://poj.org/problem?id=3284

题外话:集训结束,回学校了。在宿舍看了这题,没什么好想法,去洗澡了。转了两个澡堂都特么没开。。倒是在路上把这题想了。用回自己的电脑,不得不说苹果的字体渲染,真心高一个等级。

题意:给定两个数a和b,从a写到b,问一共写了多少个0。

分析:当然先转化为求0..a写多少个0。网上有更简单的做法,就是枚举每位作为0,则如果这一位本来是0,左边取1..a-1(不能取0,取0这位也没了),右边则可以任意取,如果取a,则右边只能取0到右边最大值。如果本来不是0,就是没什么限制地取。

然后我是类似上次49那题数位dp的做法。f[i]表示长度为i的数串有多少个0(没限制),g[i]表示长度为i的数串,第一位为0,有多少个0。

一样转化为求0..a写多少0。考虑a,假设长度为len,最高位填0的情况是g[len],最高位为x,那么1..x-1这些可以补在长度为len-1的数串前面,即(x-1)*f[len-1]。然后最高位就是x了,继续枚举每位下去(每次枚举的当前位,是计算当前位小于当前位的最大值的方案数,然后到下一位时,已经枚举过的都是当做对应的最大值)。如果这一位是x(!= 0),那么可以填1..x-1 * f[restlen],当前位填0,那么后面可以任意填。这一位是0,那么之后只能填从0到之后的最大值。(反正就是这么个意思。。意会一下吧。。)

 

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 using namespace std;
 5 
 6 #define debug 0
 7 #define bug 0
 8 long long a, b;
 9 long long f[40], g[40];
10 int d[40];
11 long long G(int x)
12 {
13     if (x == 1) return 1;
14     return G(x-1) + f[x-2] * 9;  //当前位填0,那么可以是下一位填1-9,或是下一位填0的相同情况(递归)
15 }
16 void init()
17 {
18     f[0] = 0;
19     long long exp = 1;
20     for (int i = 1; i < 40; i++){  //这一位任填0-9,所以原来的变为10倍,同时计算这位为0的总数(之前的任填)。
21         f[i] = f[i-1] * 10 + exp;
22         exp = exp * 10;
23     }
24     for (int i = 1; i < 40; i++)
25         g[i] = G(i);
26 }
27 long long cal(long long x)
28 {
29     if (debug) printf("%lld\n", x);
30     if (x == -1) return 0;
31     if (x == 0) return 1;
32     int len = 0;
33     while(x){
34         d[len++] = x % 10;
35         x /= 10;
36     }
37     long long ret = g[len] + f[len-1] * (d[len-1]-1);
38     if (debug) printf("%lld\n", ret);
39     long long exp = 1;
40     for (int i = 0; i < len-2; i++)
41         exp = exp * 10;
42     for (int i = len-2; i >= 0; i--){
43         if (d[i]) ret = ret + exp;
44         else{
45             long long tmp = 0;
46             for (int j = i-1; j >= 0; j --)
47                 tmp = tmp * 10 + d[j];
48             ret = ret + tmp + 1;
49         }
50         exp = exp / 10;
51         ret = ret + f[i] * d[i];
52     }
53     if (debug) printf("%lld\n", ret);
54     return ret;
55 }
56 int main()
57 {
58     init();
59     while(scanf("%lld %lld", &a, &b))
60     {
61         if (a < 0 || b < 0) break;
62         if (bug) printf("%lld %lld\n", cal(b), cal(a-1));
63         printf("%lld\n", cal(b) - cal(a-1));
64     }
65     return 0;
66 }

 

转载于:https://www.cnblogs.com/james47/p/3940654.html

内容概要:本文系统介绍了算术优化算法(AOA)的基本原理、核心思想及Python实现方法,并通过图像分割的实际案例展示了其应用价值。AOA是一种基于种群的元启发式算法,其核心思想来源于四则运算,利用乘除运算进行全局勘探,加减运算进行局部开发,通过数学优化器加速函数(MOA)和数学优化概率(MOP)动态控制搜索过程,在全局探索与局部开发之间实现平衡。文章详细解析了算法的初始化、勘探与开发阶段的更新策略,并提供了完整的Python代码实现,结合Rastrigin函数进行测试验证。进一步地,以Flask框架搭建前后端分离系统,将AOA应用于图像分割任务,展示了其在实际工程中的可行性与高效性。最后,通过收敛速度、寻优精度等指标评估算法性能,并提出自适应参数调整、模型优化和并行计算等改进策略。; 适合人群:具备一定Python编程基础和优化算法基础知识的高校学生、科研人员及工程技术人员,尤其适合从事人工智能、图像处理、智能优化等领域的从业者;; 使用场景及目标:①理解元启发式算法的设计思想与实现机制;②掌握AOA在函数优化、图像分割等实际问题中的建模与求解方法;③学习如何将优化算法集成到Web系统中实现工程化应用;④为算法性能评估与改进提供实践参考; 阅读建议:建议读者结合代码逐行调试,深入理解算法流程中MOA与MOP的作用机制,尝试在不同测试函数上运行算法以观察性能差异,并可进一步扩展图像分割模块,引入更复杂的预处理或后处理技术以提升分割效果。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值