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]时候 2
n后 各个位数的贡献值会翻倍,不同的是,[5,9]时各个位数的贡献值是2n-9
设cnt 是n中各个位数大于等于5的
S(2
n)= 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;
}


posted @ 2018-04-29 20:03  muvseea  阅读(178)  评论(0编辑  收藏  举报