HDU 5710 Digit-Sum (构造)
Posted 我不吃饼干呀
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了HDU 5710 Digit-Sum (构造)相关的知识,希望对你有一定的参考价值。
题意:
定义S(N) 为数字N每个位上数字的和。
在给两个数a,b,求最小的正整数n,使得 a×S(n)=b×S(2n)。
官方题解:
这道题目的结果可能非常大,所以我们直接枚举n是要GG的。
首先可以有这样的基础性结论:
设gcd(a,b)=g, 我们可以先使得b=b/g, a=a/g
S(n):S(2n)==b:a,那么我们有S(n):S(2n)=b:a。
然后,一个好的做法是,我们研究本质问题。
我们发现,如果一个digit是0~4,那么*2的效益是完全获得的。
如果一个digit的是5~9,那么*2后会损失9的收益。
a*S(n) == b*S(2n),
我们假设有l的长度是[0,4]范围,有L的长度是[5,9]范围
那么显然满足:
S(2n)=S(n)*2-L*9
替换一下——
a*S(n) == b*(2S(n)-L*9)
a*S(n) == 2b*S(n) -L*9*b
(2b-a)*S(n) == L*9*b
即——
9*b:2b-a = S(n):L
也就是说,我们得到了S(n)与L的比例关系。
然后模拟一遍即可。
怎么模拟呢?
我们不妨假设答案n仅有长度为L,且每一位都是5
然后得到了把数位和sum分撒出去。
对于sum余下的数值,我们依次加到尾巴上。
如果sum最后把长度为L的字串都填充为‘9‘之后,还有剩余,那么在前面贪心填充。
构造题一般是找规律。找到了就恍然大悟了,找不到就……我靠这题怎么这么难!
做题要大胆,细心。
代码:
#include <iostream> using namespace std; // a*s(n)=b*s(2n) // a*s(n)=b*( 2*s(n)-9*l ) // (a-b*2)*s(n)=-b*9*l // (b*2-a)/b*9=l/s(n) int gcd(int a, int b) { return b ? gcd(b, a%b) : a; } int ans[1005]; int main() { int T; cin >> T; while (T--) { int a, b; cin >> a >> b; int l = b * 2 - a; int sn = b * 9; if (5 * l > sn || l < 0) { cout << "0" << endl; continue; } if (l == 0) { cout << "1" << endl; continue; } int gg = gcd(l, sn); l /= gg; sn /= gg; int idx = 0; sn -= 5 * l; for (int i = 0; i < l; ++i) { int add = min(4, sn); sn -= add; ans[idx++] = 5 + add; } while (sn) { int res = min(4, sn); ans[idx++] = res; sn -= res; } for (int i = idx-1; i >= 0; --i) cout << ans[i]; cout << endl; } return 0; }
以上是关于HDU 5710 Digit-Sum (构造)的主要内容,如果未能解决你的问题,请参考以下文章
2019 HDU 多校赛第二场 HDU 6598 Harmonious Army 构造最小割模型