【HDU5710】Digit-Sum-思维+构造
测试地址:Digit-Sum
题目大意: 令为的十进制表示的各个数位之和,要求构造出一个最小正整数满足。
做法: 本题需要用到思维+构造。
我们尝试找出从变成后,数位和的变化。令包含的的数位有个,那么变成后就会进次位,每进一次位,个位减,十位加,所以。
于是我们就把题目中的式子改成:。于是分类讨论:
当,显然无解。
当,那么是最小的答案。
否则,先将和约分,剩下。有一个结论是,当时无解,则整个式子无解,否则当时得到的解最优。
首先无解,充要条件是,当变为时,变为,而,所以还是无解。
然后,如果时有解,一种构造的方法是,首先写出个,然后把中剩余的部分尽可能加在低位上,如果,那么就要把剩余的部分加在比位更高的那些位上,显然也是尽量加在低位上,而这些位所能填的上限都是(因为定义了是的数位数,不能影响)。这样就能构造出一个解了。
那么当,显然解不会更优,因为堆积的位数一定会更多。这样一来,我们就可以直接按照上面的方法构造了。
以下是本人代码:
#include <bits/stdc++.h>
using namespace std;
int T,a,b,digit[10010];
int gcd(int a,int b)
{
return (b==0)?a:gcd(b,a%b);
}
int main()
{
scanf("%d",&T);
while(T--)
{
scanf("%d%d",&a,&b);
int x=2*b-a,s=9*b;
if (x==0) {printf("1\n");continue;}
if (x<0) {printf("0\n");continue;}
int g=gcd(x,s);
x/=g,s/=g;
if (5*x>s) {printf("0\n");continue;}
int tot=x;
for(int i=1;i<=x;i++)
digit[i]=5;
s-=5*x;
for(int i=1;i<=x;i++)
{
digit[i]+=min(4,s);
s-=digit[i]-5;
if (!s) break;
}
while(s)
{
digit[++tot]=min(4,s);
s-=digit[tot];
}
for(int i=tot;i>=1;i--)
printf("%d",digit[i]);
printf("\n");
}
return 0;
}