原题见HDU 5710
题意:定义
S(N)
是
N
的数位之和,给出一对
分析: 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×(2S−9L)
则
(2b−a)S=9bL
1. a=2b,则L=0,S为任意值。可得最小的n=1;
2. a>2b,则L<0,矛盾!则无满足的n,输出0;
3. a<2b, S=9bL2b−a≤5L (至少有L个5),即必须满足 b≤5a ,否则无满足的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)2b−a
原来的位数(大约)是(除以4的地方应该加个向上取整)
9bL(2b−a)−9L4+L
现在的位数是
9b(L+x)(2b−a)−9(L+x)4+(L+x)
后面减前面,差值是
9bx(2b−a)−9x4+x=5a−b4(2b−a)x
又有条件
b≤5a
,则这个差值大于等于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 1000
int 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();
}
}