HDU 5710 Digit-Sum 数学杂题

来源:互联网 发布:财务报账系统 php 编辑:程序博客网 时间:2024/06/07 07:38

原题见HDU 5710

题意:定义S(N)N的数位之和,给出一对a,b(0<a,b<101)满足

a×S(n)=b×S(2n)

分析:S(n)S(2n)的关系如何?

对于n中的任何一个数位x,若x为0-4,则因为没有进位,所以在S(2n)中贡献为2x;若x为5-9,则由于其超过10,在S(2n)中贡献为2x-10+1.这里不用担心因为进位会使得高位又满10进位,事实上前一位最多为2*9=18或者是单纯的8,不可能出现9.

x 位数 S(n) S(2n) 0~4 x 2x 5~9 L x 2x-9

可见只有5~9的位数使S(n)S(2n)有了差异,即S(2n)=2S(n)9L,代入原式,S(n)S

a×S=b×(2S9L)
(2ba)S=9bL

1. a=2b,则L=0,S为任意值。可得最小的n=1;
2. a>2b,则L<0,矛盾!则无满足的n,输出0;
3. a<2b, S=9bL2ba5L(至少有L个5),即必须满足b5a,否则无满足的n,输出0。

继续讨论上述第三种情况,由于分母为2b-a,L周期性地使得右边式子可以整除,现在只要求出最小的L,枚举范围从1到2b-a必定会有满足的L。
得到一组满足的(L,S),构造最小的n。首先先要在后L位塞满5,剩下的(S-5L)开始从个位到高位塞4,直到塞完为止。

讨论:L与n的关系?

问题来了,既然L可以取多个,怎么保证最小的L使得n最小?
假设L’=L+x,S=9b(L+x)2ba
原来的位数(大约)是(除以4的地方应该加个向上取整)

9bL(2ba)9L4+L

现在的位数是
9b(L+x)(2ba)9(L+x)4+(L+x)

后面减前面,差值是
9bx(2ba)9x4+x=5ab4(2ba)x
又有条件b5a,则这个差值大于等于0.位数大的数肯定比原来大了。所以最小的L可以得到最小的n.

附代码

/*-------------------------------------------- * File Name: HDU 5710 * Author: Danliwoo * Mail: Danliwoo@outlook.com * Created Time: 2016-07-05 17:09:58--------------------------------------------*/#include <cstdio>#include <iostream>#include <cstring>#include <queue>#include <algorithm>#include <cmath>using namespace std;#define N 1000int ans[N], a, b;void solve(){    if(a == 2*b){        printf("1\n");        return;    }    if(a > 2*b || 5*a < b){        printf("0\n");        return;    }    int L, S;    for(L = 1;L < 1000;L++){        S = 9*b*L/(2*b-a);        if((2*b-a)*S == 9*b*L)            break;    }    memset(ans, 0, sizeof(ans));    for(int i = 0;i < L;i++)        ans[i] = 5;    S -= L*5;    int len;    for(int i = 0;;i++){        if(S > 4){            ans[i] += 4;            S -= 4;        } else {            ans[i] += S;            S = 0;            len = i+1;            break;        }    }    len = max(len, L);    for(int i = len-1;i >= 0;i--)        printf("%d", ans[i]);    printf("\n");}int main(){    int T;    scanf("%d", &T);    while(T--){        scanf("%d%d", &a, &b);        solve();    }}
0 0