hdu 5710 Digit-Sum (推公式)

题目链接

题意:

S(n)为n的各个位的数字之和,给出a,b,求最小的n值(n为正整数),使得a*S(n)=b*S(2*n),没有的话输出0

思路:

首先,1-9的S(n)值和S(2*n)值如下:

n             S(n)             S(2*n)                   S(2*n)-S(n)

1               1                  2                              1

2               2                  4                              2

3               3                  6                              3

4               4                  8                              4

5               5                  1                              -4

6               6                  3                              -3

7               7                  5                              -2

8               8                  7                              -1

9               9                  9                              0

其次,可以发现S(2*n)的值为S(n的各个位的数字的2倍)的和,所以我们可以凑出n中1-9的数量,在观察上面的1-9的表可以发现,2,3,4,即为2*1,3*1,4*1,6,7,8,9即为5+1,5+1*2,5+1*3,5+1*4,所以只要求出1和5的数量,就可以知道n值,因为要n最小,所以要数的位数小,尽可能多的转成9,8,……,在按1,2,3……的顺序正序输出,就是n的值了;

·设1有x个,5有y个,则可得公式 a*(x+5*y)=b*(2*x+y),可得x/y=(b-5*a)/(a-2*b),特判一下b-5*a=0和a-2*b=0的情况,

而且要求最小的n,记得求出最简的比值

 

ac代码:

#include <iostream>
#include <algorithm>
#include <cmath>
#include <cstring>
using namespace std;

int v[15];

int gcd(int x,int y){
    return x?gcd(y%x,x):y;
}

int main()
{
    int t;
    cin>>t;
    while(t--){
        memset(v,0,sizeof(v));
        int a,b;
        cin>>a>>b;
        int y=a-2*b,x=b-5*a;
        if(!x){//特判b=5*a,此时5  10符合条件
            cout<<5<<endl;
            continue;
        }
        if(!y){//特判a=2*b,此时1  2符合条件
            cout<<1<<endl;
            continue;
        }
        if(1.0*x/y<0){//比值为负证明无解
            cout<<0<<endl;
            continue;
        }
        x=abs(x),y=abs(y);
        int t=gcd(x,y);
        x/=t,y/=t;//求x和y的最简比
        for(int i=9,j=4;i>5;i--,j--){//转成尽可能少的数
            v[i]=min(y,x/j);
            y-=v[i];
            x-=v[i]*j;
        }
        v[5]=y;
        for(int j=4;j>0;j--){
            v[j]=x/j;
            x-=v[j]*j;
        }
        for(int i=1;i<10;i++){//n最小,所以最高位的数最小
            for(int j=0;j<v[i];j++){
                cout<<i;
            }
        }
        cout<<endl;
    }
    return 0;
}

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值