HDU 5710 digit sum
题意:
定义S(N) 为数字N每个位上数字的和。
在给两个数a,b,求最小的正整数n,使得 a×S(n)=b×S(2n)。
分析:
为我们要找到满足 a * S(n) = bS(2n) 的最小的n的值,首先第一个想法肯定暴力啊..但是暴力肯定不对啊... 比如--->2 3 输出5589
也就是说从整体(一个数字)到部分(各个位数)的思路是行不通的,因为是digit 所以可以尝试由部分到整体也就是构造呀。
那么如何构造呢?从若不存在S(2n) 那么我们的构造一定是从低位构造到高位。
但是有S(2n)那么是否可以根据S(N)和 S(2N)构造出一定规律呢。
题目中没有给任何信息那么,因为是发现构造规律那么是要研究2的位数。
容易发现 当位数属于[0,4]时候 2n后 各个位数的贡献值会翻倍,不同的是,[5,9]时各个位数的贡献值是2n-9
设cnt 是n中各个位数大于等于5的
S(2n)= 2*S(n)-9cnt
那么可以整理出来的是
9b:2b-a=S(n):cnt
那么我们可以得到S(n) 为 9b cnt为 2b-a
那么现在就变成了我们已经知道S(n)和cnt为多少来求最小的N
那么贪心的填一填啊
(先填后面填到9)
再填一下... 前面的...
有几个特判
1.2b-a=0时候 S为任意值 必须满足那么可以输出n=1;
2.a>2b不存在
3.a<2b 必须满足b<=5a
#include <bits/stdc++.h>
using namespace std;
int main()
{
int T;
cin>>T;
while(T--)
{
int a,b;
cin >> a >> b;
int cnt = 2*b-a;
int s = b*9;
if(a == 2*b)
{
cout << 1 <<endl;
continue;
}
if(a>2*b||5*a<b)
{
cout<< 0 <<endl;
continue;
}
int gcd = __gcd(cnt,s);
cnt/=gcd;
s/=gcd;
string ans=string(cnt,'5');
//看别人代码学到的操作这个函数很好用呀
//cout<<ans<<endl;
s-=5*cnt;
int val;
for(int i=ans.size()-1;i>=0;i--)
{
val=min(s,4);
ans[i]+=val;
s-=val;
}
while(s)
{
val=min(s,4);
ans=char(val+'0')+ans;
s-=val;
}
cout<<ans<<endl;
}
return 0;
}