📜  N的正整数倍的最小可能数字总和

📅  最后修改于: 2021-05-08 17:05:20             🧑  作者: 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。由于顶点位于0到N-1之内,所以取N为模。

答案将是从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