测试地址:Digit-Sum
题目大意: 令
S
(
n
)
S(n)
S(n)为
n
n
n的十进制表示的各个数位之和,要求构造出一个最小正整数满足
a
⋅
S
(
n
)
=
b
⋅
S
(
2
n
)
a\cdot S(n)=b\cdot S(2n)
a⋅S(n)=b⋅S(2n)。
做法: 本题需要用到思维+构造。
我们尝试找出从
n
n
n变成
2
n
2n
2n后,数位和的变化。令
n
n
n包含的
≥
5
\ge 5
≥5的数位有
x
x
x个,那么变成
2
n
2n
2n后就会进
x
x
x次位,每进一次位,个位减
10
10
10,十位加
1
1
1,所以
S
(
2
n
)
=
2
S
(
n
)
−
9
x
S(2n)=2S(n)-9x
S(2n)=2S(n)−9x。
于是我们就把题目中的式子改成:
(
2
b
−
a
)
S
(
n
)
=
9
b
⋅
x
(2b-a)S(n)=9b\cdot x
(2b−a)S(n)=9b⋅x。于是分类讨论:
当
2
b
−
a
<
0
2b-a<0
2b−a<0,显然无解。
当
2
b
−
a
=
0
2b-a=0
2b−a=0,那么
1
1
1是最小的答案。
否则,先将
2
b
−
a
2b-a
2b−a和
9
b
9b
9b约分,剩下
p
S
(
n
)
=
q
x
pS(n)=qx
pS(n)=qx。有一个结论是,当
x
=
p
,
S
(
n
)
=
q
x=p,S(n)=q
x=p,S(n)=q时无解,则整个式子无解,否则当
x
=
p
,
S
(
n
)
=
q
x=p,S(n)=q
x=p,S(n)=q时得到的解最优。
首先
x
=
p
,
S
(
n
)
=
q
x=p,S(n)=q
x=p,S(n)=q无解,充要条件是
5
x
>
S
(
n
)
5x>S(n)
5x>S(n),当
x
x
x变为
k
p
kp
kp时,
S
(
n
)
S(n)
S(n)变为
k
q
kq
kq,而
5
k
x
>
k
S
(
n
)
5kx>kS(n)
5kx>kS(n),所以还是无解。
然后,如果
x
=
p
,
S
(
n
)
=
q
x=p,S(n)=q
x=p,S(n)=q时有解,一种构造的方法是,首先写出
x
x
x个
5
5
5,然后把
S
(
n
)
S(n)
S(n)中剩余的部分尽可能加在低位上,如果
S
(
n
)
>
9
x
S(n)>9x
S(n)>9x,那么就要把剩余的部分加在比
x
x
x位更高的那些位上,显然也是尽量加在低位上,而这些位所能填的上限都是
4
4
4(因为定义了
x
x
x是
≥
5
\ge 5
≥5的数位数,不能影响)。这样就能构造出一个解了。
那么当
x
=
k
p
,
S
(
n
)
=
k
q
x=kp,S(n)=kq
x=kp,S(n)=kq,显然解不会更优,因为堆积的位数一定会更多。这样一来,我们就可以直接按照上面的方法构造了。
以下是本人代码:
#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;
}
377

被折叠的 条评论
为什么被折叠?



