hdu 5710 digit—sum数论

版权声明:小媛原创,转载请注明出处! https://blog.csdn.net/xingfushiniziji/article/details/85063164

题目链接 hdu 5710
思路题

/*竟然一道题想了两天 
对于n中的任何一个数位x,若x为0-4,则因为没有进位,
所以在S(2n)中贡献为2x;若x为5-9,则由于其超过10,在S(2n)中贡献为2x-10+1.
a*S=b*(2S*9L)
则
(2b-a)S=9*b*L
s=9bl/(2b-a);
s就是s(n),a,b就是题目中给的ab
l是某一位上为5-9的 位数 
1. a=2b,则L=0,S为任意值。可得最小的n=1; 
2. a>2b,则L<0,矛盾!则无满足的n,输出0; 
3. a<2b, S=9bL/(2b-a)≤5L (至少有L个5),即必须满足 b≤5a ,否则无满足的n,输出0。
a趋近于0,9b/2b<10b/2b,利用了放缩 
继续讨论上述第三种情况,由于分母为2b-a,L周期性地使得右边式子可以整除,现在只要求出最小的L,
枚举范围从1到2b-a必定会有满足的L。 
得到一组满足的(L,S),构造最小的n。最小的n,最小的l首
先要在后L位塞满5,剩下的(S-5L)开始从个位到高位塞4,直到塞完为止。
故 S(n)=k*(9b) ,
L=k*(2b-a)同时,由于要求 n 最小,可知 k 取 1 时最小。
在已有 S(n)以及 L 的情况下,求 n ?
首先构造长为 L ,每个字符均为 5 (由于 L 个数字必须 >= 5)的字符串,
同时 S(n)-=5×L 。对于多余的 S(n) ,
为使得 n 尽可能小(即串长最小,大的数字尽可能向个位数靠拢)。故优先将串尾的字符增长到 9 。
若长为 L 的字符串已经全部为 9 。此时不得不增加串长,则优先在串首增加 4 (不在 L 个数字中的均 <= 4),直到 S(n)S(n) 全部用尽。

*/

#include<cstdio>
#include<iostream>
#include<algorithm>
using namespace std;
int main()
{
	int t,a,b,s,l,GCD,add;//add代表加的值 
	scanf("%d",&t);
	while(t--){
		scanf("%d%d",&a,&b);
		if(a>2*b||b>5*a) printf("0\n");
		else{
			l=2*b-a;
			s=9*b;
			GCD=__gcd(l,s);
			l/=GCD;
			s/=GCD;
			string ans=string(l,'5');//先把l里面都换成5;
			s-=5*l;
			for(int i=ans.size()-1;i+1;i--){//要想使位数比较小,需要各位为9 
				add=min(s,4);//如果sn>4,5+4=9,如果小于4 ,直接 加原来的 
				ans[i]+=add;
				s-=add;
			}
			while(s){//如果变成9 还不够,那就要把串长增加
			    add=min(s,4);
			    ans=char(add+'0')+ans;
			    s-=add;
		    }
		    printf("%s\n",ans.c_str());
		    //C语言中没有string类,字符串使用char指针来实现的。
            //C与C++本身就是一家,为了让它们在一定程度上可以通用,就有了.c_str()函数。
		}
		
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/xingfushiniziji/article/details/85063164