DigitalCounter

日常发题:

我们有一个N位数字的电子表,当时间到达10^N-1时,下一秒就归0。下面我们给出数字0 到 9的模拟图。
在这里插入图片描述
 对于每个数字,相邻两个+之间会有一根电子管,当显示该数字时,这些电子管就会发亮。如上图所示:数字0到9,它们的电子管数量分别是:6、2、 5、 5、 4、 5、 6、 3、 7、 5。
  设现在的时刻是X, 那么可以算出该时有多少根电子管是亮的。比如:现在时刻是:99,那么共有5 + 5= 10根电子管是亮的。假如从现在时刻开始,再过Y秒后,时刻显示为Z, 我们的问题是:求最小的Y,使得时刻Z发亮的电子管数量与时刻X发亮的电子管数量相等。如:现在X = 99 ,那么再过Y = 5 秒后, 时刻变成了Z = 04, 而时刻Z发亮的电子管数量 = 6 + 4 = 10。于是Y = 5就是你要求的数。

输入:
第一行:一个整数N,表示电子表是10^N进制的。1 <= N <= 15。
第二行:一个整数X, 表示现在的时刻,可能有前导0。X有N位数字。

输出:
一行:最小的整数Y, 表示从现在X时刻开始,再过Y秒,得到的时刻Z发亮的电子管数量与时刻X发亮的电子管数量相等。

分析:

这道题题目大意就是说:有一个电子表,有n位,每秒加1,当达到999…(n个9)时,电子表归零(即000…(n个0))。每个数字都有一个电子管数(数字0到9,它们的电子管数量分别是:6、2、5、5、4、5、6、3、7、5)。问过了多少秒后用的电子管数一样?

30~60分:暴力。
从当前时间+1开始枚举,每次判断是否等于原来的电子管数,爆表就归零,找到就输出。如果Pascal就30,C++就60。(嗯?有点不符合逻辑?也许是个人问题吧!)

70分:剪枝(方法多种多样,我不太了解)。

正解来了:

我们首先枚举 i = n . . . 1 i=n...1 i=n...1(其实就是从个位开始枚举),接着枚举 j = a [ i ] + 1...9 j=a[i]+1...9 j=a[i]+1...9 a [ i ] a[i] a[i]就是当前的那一位)
这里的意思就是说我们枚举应从低位开始,枚举修改哪一位。
那怎么判断这一位是否合法呢?先给大家看两个命题:

① s u m [ i − 1 ] + n u m [ j ] + ( n − i ) ∗ 7 &gt; = s u m [ n ] ① sum[i-1]+num[j]+(n-i)*7&gt;=sum[n] sum[i1]+num[j]+(ni)7>=sum[n]
② s u m [ i − 1 ] + n u m [ j ] + ( n − i ) ∗ 2 &lt; = s u m [ n ] ② sum[i-1]+num[j]+(n-i)*2&lt;=sum[n] sum[i1]+num[j]+(ni)2<=sum[n]

这里的 s u m [ i ] sum[i] sum[i]代表读入的前i个数字所用的电子管数之和(即前缀和), n u m [ i ] num[i] num[i]代表数字i所用的电子管数。
那么很显然, s u m [ n ] sum[n] sum[n]代表的就是所用电子管总和,最后剩下 ( n − i ) ∗ 7 (n-i)*7 (ni)7 ( n − i ) ∗ 2 (n-i)*2 (ni)2,代表后i位全都取最大( 8 8 8,要7个电子管)或取最小( 1 1 1,要2个电子管)。

分析①,如果说后 i i i位数字全部取最大都达不到(小于)所用电子管总和(即 s u m [ n ] sum[n] sum[n]),必然不可能和为所用电子管总和。所以一定要>= s u m [ n ] sum[n] sum[n]
由上面的解释,②也同理,如果说后i位数字全部取最小都达不到(大于)所用电子管总和(即 s u m [ n ] sum[n] sum[n]),必然不可能和为所用电子管总和。所以一定要<= s u m [ n ] sum[n] sum[n]
回到枚举,只要符合这两个命题,就保存下 i i i j j j
第二步,分两种情况:

  1. 找到了 i i i j j j
    只要从 i + 1 i+1 i+1枚举到 n n n(即剩下需要找的位)
    再枚举 0...9 0...9 0...9(这里之所以可以直接 0 0 0 9 9 9,是因为第i位必然会变大,之后的位就可以随便选了)
    这里加入两个个新变量:
    S U M SUM SUM,先保存第一步确定的前i位的电子管数之和。
    ¥S$,保存第一步确定的前i位的数字(这是个字符串)。
    每次判断的和上面很类似:
    S U M + n u m [ j ] + ( n − i ) ∗ 7 &gt; = s u m [ n ] SUM+num[j]+(n-i)*7&gt;=sum[n] SUM+num[j]+(ni)7>=sum[n]
    S U M + n u m [ j ] + ( n − i ) ∗ 2 &lt; = s u m [ n ] SUM+num[j]+(n-i)*2&lt;=sum[n] SUM+num[j]+(ni)2<=sum[n](SUM就是变化的地方)
    同理。
    每次第二重循环找到了一位,就退出(第二重),找下一位。
    答案就是S转成的数字减原来的时间差。
  2. 第二种。i和j找不到了。
    1... n 1...n 1...n枚举,再枚举 0...9 0...9 0...9,这次的 S U M , S SUM,S SUM,S都是空的。
    同上,判断即可。
    答案就是电子表最大值加1(即 1 0 n 10^n 10n)-原来的时间+S转成的数字。(即算出爆表的时间+归零后重新算的时间)

如有不妥,请留言改正。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值