How to find the smallest number with just 0 and 1 which is divided by a given number?

后端 未结 11 1282
情话喂你
情话喂你 2020-11-29 22:44

Every positive integer divide some number whose representation (base 10) contains only zeroes and ones.

One can prove that:

Consider the numbers 1, 11, 111,

相关标签:
11条回答
  • 2020-11-29 23:08

    Here is complete c# code in O(n) using graph and bfs approach.

    using System;
    using System.Collections.Generic;
    using System.Collections;
    using System.Security.Cryptography;
    using System.Linq;
    using System.Runtime.InteropServices;
    
    class Solution {
        public class Edge : IComparable
        {
            public int From
            {
                get;
                set;
            }
            public int To
            {
                get;
                set;
            }
            public int Weight
            {
                get;
                set;
            }
            public bool IsDirected
            {
                get;
                set;
            }
    
            public Edge(int from, int to, bool isDirected = false, int weight = 0)
            {
                this.From = from;
                this.To = to;
                this.Weight = weight;
                this.IsDirected = isDirected;
            }
    
            public int CompareTo(object obj)
            {
                if (obj is Edge)
                {
                    var comparingTo = obj as Edge;
                    return this.Weight.CompareTo(comparingTo.Weight);
                }
                return 0; //TODO:what should we return?
            }
        }
    
        public class AdjNode
        {
            public int EdgeWeight
            {
                get;
                set;
            }
    
            public int Id
            {
                get;
                set;
            }
    
            public AdjNode(int id)
            {
                this.Id = id;
                this.EdgeWeight = 0;
            }
            public AdjNode(int id, int weight)
            {
                this.Id = id;
                this.EdgeWeight = weight;
            }
        }
        public class GraphAdj
        {
    
            public int V
            {
                get;
                set;
            }
    
            public List<AdjNode>[] adj
            {
                get;
                set;
            }
    
            public List<Edge> Edges
            {
                get;
                set;
            }
    
            public GraphAdj(int v)
            {
                this.V = v;
                this.adj = new List<AdjNode>[this.V];
                for (int i = 0; i < this.V; i++)
                {
                    this.adj[i] = new List<AdjNode>(); //allocate actual memory
                }
                this.Edges = new List<Edge>();
            }
    
            public void AddDirectedEdge(int from, int to)
            {
                adj[from].Add(new AdjNode(to));
                this.Edges.Add(new Edge(from,to,true));
            }
    
            public void AddDirectedEdge(int from, int to, int weight)
            {
                adj[from].Add(new AdjNode(to,weight));
                this.Edges.Add(new Edge(from, to, true, weight));
            }
        }
        public string multiple(int A) {
            int n = A;
            GraphAdj directedGraphForNumber = new GraphAdj(n);
            Queue<int> queueForNumbers = new Queue<int>();
                string result = String.Empty;
                bool[] visitedForNumbers = new bool[directedGraphForNumber.V];
                int[] suffixes = new int[2] { 0, 1 };
                //we will start from 1st node out of n node
    
                queueForNumbers.Enqueue(1);
                visitedForNumbers[1] = true;
    
                while (true)
                {
                    int from = queueForNumbers.Dequeue();
                    if (from == 0)
                        break;
    
                    for (int i = 0; i < suffixes.Length; i++)
                    {
                        int toNode = from * 10 + suffixes[i];
                        int reminder = toNode % n;
                        if (visitedForNumbers[reminder] == false)
                        {
                            visitedForNumbers[reminder] = true;
                            queueForNumbers.Enqueue(reminder);
                            directedGraphForNumber.AddDirectedEdge(from, reminder,suffixes[i]);
                        }
                    }
                }
    
                //Do BFS traversal with edges until zero th node encounters
                bool[] visitedForBfs = new bool[directedGraphForNumber.V];
                Queue<int> queueForBfs = new Queue<int>();
                int[] parent = new int[directedGraphForNumber.V];
    
                int source = 1;
                visitedForBfs[source] = true;
                queueForBfs.Enqueue(source);
                parent[source] = -1;
    
                while (queueForBfs.Count > 0)
                {
                    int currentVertex = queueForBfs.Dequeue();
    
                    foreach (var adjacentVertex in directedGraphForNumber.adj[currentVertex])
                    {
                        if (visitedForBfs[adjacentVertex.Id] == false)
                        {
                            queueForBfs.Enqueue(adjacentVertex.Id);
                            parent[adjacentVertex.Id] = currentVertex;
                            visitedForBfs[adjacentVertex.Id] = true;
                        }
                        if (adjacentVertex.Id == 0) // we reach zero th node
                        {
                            queueForBfs.Clear(); //break out of bfs
                        }
                    }
                }
    
                //now time to find path all the way to start from zero using parent
                List<int> pathListUsingParent = new List<int>();
                int current = 0;
                pathListUsingParent.Add(0); // add zero
    
                while (current!=1)
                {
                    pathListUsingParent.Add(parent[current]);
                    current = parent[current];
                }
    
                //reverse path to make number using edges
                pathListUsingParent.Reverse();
    
                result += "1"; //start node
    
                //now read edges
                for (int i = 0; i < pathListUsingParent.Count-1; i++)
                {
                    int from = pathListUsingParent[i];
                    int to = pathListUsingParent[i + 1];
    
                    result += directedGraphForNumber.adj[from].FirstOrDefault(adj => adj.Id == to).EdgeWeight;
                }
    
                return result;
        }
    }
    
    0 讨论(0)
  • 2020-11-29 23:10

    This is a fast way to get the first 792 answers. Def the most simple code:

    __author__ = 'robert'
    
    from itertools import product
    
    def get_nums(max_length):
        assert max_length < 21 #Otherwise there will be over 2 million possibilities
        for length in range(1, max_length + 1):
            for prod in product("10", repeat=length):
                if prod[0] == '1':
                    yield int("".join(prod))
    
    print list(get_nums(4))
    [1, 11, 10, 111, 110, 101, 100, 1111, 1110, 1101, 1100, 1011, 1010, 1001, 1000]
    
    nums = sorted(get_nums(20))
    print len(nums)
    
    solution = {}
    
    operations = 0
    
    for factor in range(1, 1000):
        for num in nums:
            operations += 1
            if num % factor == 0:
                solution[factor] = num
                break
        print factor, operations
        if factor not in solution:
            print "no solution for factor %s" % factor
            break
    
    print solution[787]
    
    max_v = max(solution.values())
    for factor, val in solution.items():
        if val == max_v:
            print factor, max_v
    
    
    [1, 11, 10, 111, 110, 101, 100, 1111, 1110, 1101, 1100, 1011, 1010, 1001, 1000]
    1048575
    1 1
    2 3
    3 10
    4 14
    5 16
    6 30
    7 39
    8 47
    9 558
    10 560
    11 563
    12 591
    13 600
    14 618
    15 632
    16 648
    17 677
    18 1699
    19 1724
    20 1728
    ..
    ..
    187 319781
    188 319857
    ..
    ..
    791 4899691
    792 5948266
    no solution for factor 792
    10110001111
    396 11111111111111111100
    
    0 讨论(0)
  • 2020-11-29 23:12
    using System;
    using System.Collections.Generic;
    using System.Diagnostics;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    
    namespace ConsoleApplication2
    {
        class Class1
        {
            public static void Main()
            {
    
                List<string> possibleCombination = new List<string>();
    
                for (int i = 2; i < 10000; i++)
                {
                    possibleCombination.Add(Convert.ToString(i, 2));
                }
    
                var input = Console.ReadLine();
    
    
    
                long output = 0;
    
                foreach (var item in possibleCombination)
                {
                    if (Convert.ToInt64(item) % Convert.ToInt64(i) == 0)
                    {
                        output = Convert.ToInt64(item);
                        break;
                    }
                }
    
                Console.WriteLine(output);
    
                Console.ReadLine();
            }
    
        }
    }
    
    0 讨论(0)
  • 2020-11-29 23:16

    The question equals to using 10i mod n (for each i, it can be used at most once) to get a sum m of n. It's like a knapsack problem or subset sum problem. In this way, dynamic programming will do the task.

    In dynamic programming the complexity is O(k*n). k is the number of digits in answer. For n<105, this code works perfectly.

    Code:

    #include <stdio.h>
    #define NUM 2000
    
    int main(int argc, char* argv[])
    {
        signed long pow[NUM],val[NUM],x,num,ten;
        int i,j,count;
        for(num=2; num<NUM; num++)
        {
            for(i=0; i<NUM; pow[i++]=0);
            count=0;
            for(ten=1,x=1; x<NUM; x++)
            {
                val[x]=ten;
    
                for(j=0; j<NUM; j++)if(pow[j]&&!pow[(j+ten)%num]&&pow[j]!=x)pow[(j+ten)%num]=x;
                if(!pow[ten])pow[ten]=x;
                ten=(10*ten)%num;
                if(pow[0])break;
            }
    
            x=num;
            printf("%ld\tdivides\t",x=num);
            if(pow[0])
            {
                while(x)
                {
                    while(--count>pow[x%num]-1)printf("0");
                    count=pow[x%num]-1;
                    printf("1");
                    x=(num+x-val[pow[x%num]])%num;
                }
                while(count-->0)printf("0");
            }
            printf("\n");
        }
    }
    

    PS: This sequence in OEIS.

    0 讨论(0)
  • 2020-11-29 23:20

    My algorithm will be :-

    1)Construct the sorted tree of of n possible numbers(say n initially is 10). So in this example it will contain 1,10,11,100,101,110,111....

    2)Then loop over the list and perform on each no x%GivenNo, if its o its smallest possible no

    3)Otherwise repeat step 3 with another 10 numbers

    0 讨论(0)
  • 2020-11-29 23:22

    Here is a readable solution using BFS in java. The approach is similar to David's with some improvements.

    You build a decision tree of whether to append a 0 or 1 and perform BFS to find the lowest such valid multiple of the input number.

    This solution also leverages modulo (of the input number) to compute really large results. Full description available in the comments in the code.

    You can also access the same code snippet in ideone.

    import java.util.ArrayDeque;
    import java.util.Arrays;
    import java.util.HashSet;
    import java.util.Queue;
    import java.util.Scanner;
    import java.util.Set;
    
    public class Main {
        // Return the smallest multiple of the number (as a string) consisting only of digits 0 and 1
        //
        // All possible digits that can be constructed using the digits 0/1 can be represented
        // as a tree, where at each level, appending a 0 is one branch and appending a 1 is another
        //
        // If we perform BFS on this tree, the first number we see which is an exact multiple of the input
        // number will be the result (since it will be the smallest). Make sure to consider left
        // branch (i.e. 0) before considering the right branch (i.e. 1)
        //
        // The 2 paths we take at each level when the current number is num:
        //      (num * 10)
        //      (num * 10) + 1
        // 
        // Since the result can grow huge quite easily, it might not be possible to store the result in a
        // 32 or even a 64 bit int/long variable.
        //
        // One alternative is to use BigNumber, but a simpler alternative exists if we leverage modulo.
        //
        // The operations we perform above (i.e. multiplications and additions) will retain the useful part
        // of the result when using modulo. We use the given number itself as the modulo, and when we see a
        // result of 0, it means we have found a number which is an exact multiple of the input number.
        //
        // To reconstruct the number, we need to store the parent nodes of each node, when adding the node
        // in the queue (similar to using BFS for computing shortest path)
        //
        // We will also need to know if we appended a 0 or a 1 at each step, and so we add this information
        // as part of the node data structure as well.
        //
        // Re-visiting nodes is unecessary since we have seen this modulo result (i.e. value % num) already.
        // Any additional digits we add from now will only make the number longer and we already are tracking
        // the path for this same modulo result we've seen earlier.
        //
        public static String multiple(int num) {
            if (num < 0) {
                throw new IllegalArgumentException("Invalid args");
            }
    
            String result = "0";
    
            if (num > 0) {
                // An array to mark all the visited nodes
                boolean[] isVisited = new boolean[num];
                Arrays.fill(isVisited, false);
    
                // The queue used by BFS
                Queue<Node> queue = new ArrayDeque<>();
    
                // Add the first number 1 and mark it visited
                queue.add(new Node(true, 1 % num, null));
                isVisited[1 % num] = true;
    
                // The final destination node which represents the answer
                Node destNode = null;
    
                while (!queue.isEmpty()) {
                    // Get the next node from the queue
                    Node currNode = queue.remove();
    
                    if (currNode.val == 0) {
                        // We have reached a valid multiple of num
                        destNode = currNode;
                        break;
                    } else {
                        // Visit the next 2 neighbors
                        // Append 0 - (currNode.val * 10)
                        // Append 1 - (currNode.val * 10) + 1
    
                        // Append a '0'
                        int val1 = (currNode.val * 10) % num;
                        if (!isVisited[val1]) {
                            queue.add(new Node(false, val1, currNode));
                            isVisited[val1] = true;
                        }
    
                        // Append a '1'
                        int val2 = (val1 + 1) % num;
                        if (!isVisited[val2]) {
                            queue.add(new Node(true, val2, currNode));
                            isVisited[val2] = true;
                        }
                    }
                }
    
                // Trace the path from destination to source
                if (destNode == null) {
                    throw new IllegalStateException("Result should not be null");
                } else {
                    StringBuilder reverseResultBuilder = new StringBuilder();
                    Node currNode = destNode;
                    while (currNode != null) {
                        reverseResultBuilder.append(currNode.isDigitOne ? '1' : '0');
                        currNode = currNode.parent;
                    }
                    result = reverseResultBuilder.reverse().toString();
                }
            }
    
            return result;
        }
    
        // Node represents every digit being appended in the decision tree
        private static class Node {
            // True if '1', false otherwise (i.e. '0')
            public final boolean isDigitOne;
            // The number represented in the tree modulo the input number
            public final int val;
            // The parent node in the tree
            public final Node parent;
    
            public Node(boolean isDigitOne, int val, Node parent) {
                this.isDigitOne = isDigitOne;
                this.val = val;
                this.parent = parent;
            }
        }
    
        public static void main(String[] args) {
            int num = new Scanner(System.in).nextInt();
            System.out.println("Input number: " + num);
            System.out.println("Smallest multiple using only 0s and 1s as digits: " + Main.multiple(num));
        }
    }
    
    0 讨论(0)
提交回复
热议问题