给定一个数 N,找出可以从 N 的正倍数得到的最小可能的数字总和。
约束条件:1<=N<=10^5。
例子:
Input : N = 6
Output : 3
Explanation: 6*2 = 12, sum of digits is 1+2 = 3.
Input : N = 20
Output : 1
20*5 = 100, sum of digits is 1+0+0=1
方法:问题完全基于观察。对于 N = 6,答案是 12。
所以我们可以把 12 写成:1-(*10)–>10–(+1)–>11–(+1)–>12。该序列描述的是我们可以写出任何大于等于 1 的数,作为 +1 和 *10 的乘积之和,从 1 开始。
另一个观察结果是,当我们在数字上加上 +1 时,数字总和会增加 +1,除非最后一位数字是 9。
第二个观察结果是,当我们将数字乘以 10 时,数字之和保持不变。
现在,由于我们想要 N 的倍数,因此 N % N 的任何倍数都将为 0。
所以,综合上面的分析,我们可以构建K个顶点的图,对于任意一个顶点X,X到X+1的节点权重为1,X到(X*10)%N的节点权重为为 0。我们取模 N,因为顶点位于 0 到 N-1 之间。
答案将是从 1 到 0 的最短距离,因为 (N 的任意倍数) mod N = 0。
我们可以使用 Dijkstra 定理来找到 1 和 0 之间的最短距离。令其为 d。答案将是 1+d,因为我们还必须考虑边 0 到 1。
该解决方案的时间复杂度为 O(E+VLogV) = O(N+NLogN) = O(NlogN),因为我们最多将经过 N 个顶点和边。
还有一点要注意,因为在 xyz..9 之后,下一个数字将是 abc..0,但这不会影响我们的答案。
证明:以 N = 11 为例,答案是 2。它来自 11*1 = 11 和 11*10 = 110。
由于 110 是 N 的 10 的倍数,也是一个答案,要么我们已经找到答案,因为如果 110 是 N 的某个 10 的倍数,那么必须存在一个小于这个的数字,我们的答案中没有前导 0,即 11 .
因此,如果不是答案,我们将超过 N 的 10 的倍数,或者如果答案是 N 的某个 10 的倍数,那么我们之前已经找到了答案。
下面是上述方法的实现:
#include
using namespace std;
const int Maxx = 100005;
int N;
vector > Graph[Maxx];
/// Dijkartas algorithm to find the shortest distance
void Dijkartas(int source)
{
priority_queue, vector >,
greater > > PQ;
// Initialize all distances to be infinity
vector Distance(N + 2, 1e9);
// Push source in Priority Queue
PQ.push(make_pair(0, source));
int src = source;
Distance[src] = 0;
while (!PQ.empty()) {
int current = PQ.top().second;
PQ.pop();
for (auto& neighbours : Graph[current]) {
int v = neighbours.first;
int weight = neighbours.second;
if (Distance[v] > Distance[current] + weight) {
Distance[v] = Distance[current] + weight;
PQ.push(make_pair(Distance[v], v));
}
}
}
cout << "Minimum possible sum of digits is " <<
1 + Distance[0] << endl;
return;
}
// Function to calculate the minimum possible sum of digits
void minSumDigits(int N)
{
// Build a graph of N vertices with edge weight 1
for (int i = 1; i <= N; ++i) {
int From = (i) % N;
int To = (i + 1) % N;
int Wt = 1;
Graph[From].push_back(make_pair(To, Wt));
}
// In the same graph add weights 0 to 10's multiple of node X
for (int i = 1; i <= N; ++i) {
int From = (i) % N;
int To = (10 * i) % N;
int Wt = 0;
Graph[From].push_back(make_pair(To, Wt));
}
// Run dijartas to find the shortest distance from 1 to 0
Dijkartas(1);
return;
}
// Driver Code
int main()
{
N = 19;
minSumDigits(N);
return 0;
}
Minimum possible sum of digits is 2
如果您希望与专家一起参加现场课程,请参阅DSA 现场工作专业课程和学生竞争性编程现场课程。