📌  相关文章
📜  N 的正倍数的最小可能数字总和

📅  最后修改于: 2021-10-26 05:53:43             🧑  作者: Mango

给定一个数 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 现场工作专业课程学生竞争性编程现场课程。