📌  相关文章
📜  将数字分为可被给定数字整除的两部分

📅  最后修改于: 2021-04-29 15:14:04             🧑  作者: Mango

给定一个很大的字符串格式的数字,我们还给出了两个数字f和s。我们需要将大量数字分成两个连续的部分,以使第一部分可被f整除,第二部分可被s整除。
例子:

Input: num = “246904096”
          f = 12345        
          s = 1024
Output: Yes
We can divide num into “24680” and “4096” 
which are divisible by f and s respectively.

Input : num = “1234”
          f = 1            
          s = 123
Output : No
We can not divide num into two parts under 
given constraint.

一个简单的解决方案是生成给定数字的所有除法,并检查除法是否可除。

我们可以通过存储给定字符串的每个前缀和后缀的余数来解决此问题,如果在任何索引处,前缀提醒和后缀提醒都为零,那么我们知道可以在此索引处中断字符串。上面的示例说明了该过程,

String = “246904096”
All prefix reminders with 12345 are,

Prefix 2     reminder with 12345, 2
prefix 24      reminder with 12345, 24
prefix 246       reminder with 12345, 246
prefix 2469       reminder with 12345, 2469
prefix 24690       reminder with 12345, 0
prefix 246904       reminder with 12345, 4
prefix 2469040   reminder with 12345, 40
prefix 24690409  reminder with 12345, 409
prefix 246904096 reminder with 12345, 4096

All suffix reminder with 1024 are, 
Suffix 6     reminder with 1024, 6
Suffix 96     reminder with 1024, 96
Suffix 096     reminder with 1024, 96
Suffix 4096     reminder with 1024, 0
Suffix 04096     reminder with 1024, 0
Suffix 904096     reminder with 1024, 928
Suffix 6904096     reminder with 1024, 288
Suffix 46904096     reminder with 1024, 800
Suffix 246904096 reminder with 1024, 288
Now we can see that at index 5 both reminders
are 0, so the string can be broken into 24680
and 4096.

我们可以通过第(i – 1)个后缀提醒获得第(i)个后缀提醒,为(sr [i] = sr [i – 1] * 10 + s [i])%f,即仅将前一个提醒乘以10并添加当前数字,然后按f进行提醒。
为了通过第(i + 1)个前缀提醒获取第(i)个前缀提醒,我们可以做到(pr [i] = pr [i + 1] + s [i] * base)%s,即添加下一个提醒和当前数字乘以基值,最后一个数字为1,第二个最后一个数字为10,依此类推,然后我们以s为单位进行提醒。

解决方案的总时间复杂度将为O(N)

C++
// C++ code to break the number string into
// two divisible parts by given numbers
#include 
using namespace std;
  
// method prints divisible parts if possible, 
// otherwise prints 'Not possible'
void printTwoDivisibleParts(string num, int f, int s)
{
    int N = num.length();
  
    // creating arrays to store reminder
    int prefixReminder[N + 1];
    int suffixReminder[N + 1];
  
    suffixReminder[0] = 0;
  
    // looping over all suffix and storing 
    // reminder with f
    for (int i = 1; i < N; i++) 
  
        // getting suffix reminder from previous
        // suffix reminder
        suffixReminder[i] = (suffixReminder[i - 1] * 10 + 
                            (num[i - 1] - '0')) % f;    
  
    prefixReminder[N] = 0;
    int base = 1;
  
    // looping over all prefix and storing 
    // reminder with s
    for (int i = N - 1; i >= 0; i--) {
  
        // getting prefix reminder from next 
        // prefix reminder
        prefixReminder[i] = (prefixReminder[i + 1] + 
                           (num[i] - '0') * base) % s;
  
        // updating base value
        base = (base * 10) % s;
    }
  
    // now looping over all reminders to check 
    // partition condition
    for (int i = 0; i < N; i++) {
  
        // if both reminders are 0 and digit itself 
        // is not 0, then print result and return
        if (prefixReminder[i] == 0 && 
            suffixReminder[i] == 0 && 
            num[i] != '0') {
            cout << num.substr(0, i) << " " 
                 << num.substr(i) << endl;
            return;
        }
    }
  
    // if we reach here, then string can' be 
    // partitioned under constraints
    cout << "Not Possible\n";
}
  
// Driver code to test above methods
int main()
{
    string num = "246904096";
    int f = 12345;
    int s = 1024;
    printTwoDivisibleParts(num, f, s);
    return 0;
}


Java
// Java program to break the number string
// into two divisible parts by given numbers
public class DivisibleParts
{
    // method prints divisible parts if 
    // possible, otherwise prints 'Not possible'
    static void printTwoDivisibleParts(String num, 
                                     int f, int s)
    {
    int N = num.length();
  
    // creating arrays to store reminder
    int[] prefixReminder = new int[N + 1];
    int[] suffixReminder = new int[N + 1];
  
    suffixReminder[0] = 0;
  
    // looping over all suffix and storing 
    // reminder with f
    for (int i = 1; i < N; i++) 
  
        // getting suffix reminder from 
        // previous suffix reminder
        suffixReminder[i] = (suffixReminder[i - 1] * 10 + 
                        (num.charAt(i - 1) - '0')) % f; 
  
    prefixReminder[N] = 0;
    int base = 1;
  
    // looping over all prefix and storing 
    // reminder with s
    for (int i = N - 1; i >= 0; i--) {
  
        // getting prefix reminder from next 
        // prefix reminder
        prefixReminder[i] = (prefixReminder[i + 1] + 
                        (num.charAt(i ) - '0') * base) % s;
  
        // updating base value
        base = (base * 10) % s;
    }
  
    // now looping over all reminders to 
    // check partition condition
    for (int i = 0; i < N; i++) {
  
        // if both reminders are 0 and digit
        // itself is not 0, then print result
        // and return
        if (prefixReminder[i] == 0 && 
            suffixReminder[i] == 0 && 
            num.charAt(i ) != '0') {
                System.out.println( num.substring(0, i) 
                           +" " + num.substring(i));
            return;
        }
    }
  
    // if we reach here, then string can' be 
    // partitioned under constraints
        System.out.println("Not Possible");
      
    }
      
    /* Driver program */
    public static void main(String[] args) 
    {
    String num = "246904096";
    int f = 12345;
    int s = 1024;
    printTwoDivisibleParts(num, f, s);
    }
}
// This code is contributed by Prerna Saini


Python3
# Python3 code to break the 
# number string into two 
# divisible parts by given
# numbers
  
# method prints divisible 
# parts if possible, otherwise 
# prints 'Not possible'
def printTwoDivisibleParts(num, f, s):
    N = len(num);
  
    # creating arrays 
    # to store reminder
    prefixReminder = [0]*(N + 1);
    suffixReminder = [0]*(N + 1);
  
  
    # looping over all 
    # suffix and storing 
    # reminder with f
    for i in range(1,N): 
  
        # getting suffix 
        # reminder from previous
        # suffix reminder
        suffixReminder[i] = (suffixReminder[i - 1] * 10 + 
                            (ord(num[i - 1]) - 
                                        48)) % f; 
  
    base = 1;
  
    # looping over all 
    # prefix and storing 
    # reminder with s
    for i in range(N - 1,-1,-1):
  
        # getting prefix 
        # reminder from next 
        # prefix reminder
        prefixReminder[i] = (prefixReminder[i + 1] + 
                            (ord(num[i]) - 48) * 
                                        base) % s;
  
        # updating base value
        base = (base * 10) % s;
  
    # now looping over 
    # all reminders to check 
    # partition condition
    for i in range(N):
  
        # if both reminders are
        # 0 and digit itself 
        # is not 0, then print 
        # result and return
        if (prefixReminder[i] == 0 and suffixReminder[i] == 0 and num[i] != '0'): 
            print(num[0:i],num[i:N]);
            return 0;
  
    # if we reach here, then 
    # string can' be partitioned
    # under constraints
    print("Not Possible");
  
# Driver code 
if __name__=='__main__':
    num = "246904096";
    f = 12345;
    s = 1024;
    printTwoDivisibleParts(num,f, s);
  
# This code is contributed 
# by mits


C#
// C# program to break the 
// number string into two 
// divisible parts by given 
// numbers
using System;
class GFG
{
// method prints divisible 
// parts if possible, otherwise
// prints 'Not possible'
static void printTwoDivisibleParts(String num, 
                                   int f, int s)
{
int N = num.Length;
  
// creating arrays to
// store reminder
int[] prefixReminder = new int[N + 1];
int[] suffixReminder = new int[N + 1];
  
suffixReminder[0] = 0;
  
// looping over all 
// suffix and storing 
// reminder with f
for (int i = 1; i < N; i++) 
  
    // getting suffix reminder from 
    // previous suffix reminder
    suffixReminder[i] = (suffixReminder[i - 1] * 10 + 
                        (num[i - 1] - '0')) % f; 
  
prefixReminder[N] = 0;
int base1 = 1;
  
// looping over all 
// prefix and storing 
// reminder with s
for (int i = N - 1; i >= 0; i--)
{
  
    // getting prefix reminder 
    // from next prefix reminder
    prefixReminder[i] = (prefixReminder[i + 1] + 
                    (num[i] - '0') * base1) % s;
  
    // updating base1 value
    base1 = (base1 * 10) % s;
}
  
// now looping over all 
// reminders to check 
// partition condition
for (int i = 0; i < N; i++)
{
  
    // if both reminders are 
    // 0 and digit itself is
    // not 0, then print result
    // and return
    if (prefixReminder[i] == 0 && 
        suffixReminder[i] == 0 && 
        num[i] != '0') 
    {
            Console.WriteLine(num.Substring(0, i) + 
                            " " + num.Substring(i));
        return;
    }
}
  
// if we reach here, then 
// string can' be partitioned 
// under constraints
    Console.WriteLine("Not Possible");
  
}
  
// Driver Code
public static void Main() 
{
    String num = "246904096";
    int f = 12345;
    int s = 1024;
    printTwoDivisibleParts(num, f, s);
}
}
  
// This code is contributed by mits


PHP
= 0; $i--) 
    {
  
        // getting prefix 
        // reminder from next 
        // prefix reminder
        $prefixReminder[$i] = ($prefixReminder[$i + 1] + 
                              (ord($num[$i]) - 48) * 
                                        $base) % $s;
  
        // updating base value
        $base = ($base * 10) % $s;
    }
  
    // now looping over 
    // all reminders to check 
    // partition condition
    for ($i = 0; $i < $N; $i++) 
    {
  
        // if both reminders are
        // 0 and digit itself 
        // is not 0, then print 
        // result and return
        if ($prefixReminder[$i] == 0 && 
            $suffixReminder[$i] == 0 && 
            $num[$i] != '0') 
        {
            echo substr($num, 0, $i)." ".
                    substr($num,$i)."\n";
            return;
        }
    }
  
    // if we reach here, then 
    // string can' be partitioned
    // under constraints
    echo "Not Possible\n";
}
  
// Driver code 
$num = "246904096";
$f = 12345;
$s = 1024;
printTwoDivisibleParts($num, 
                       $f, $s);
  
// This code is contributed 
// by mits
?>


输出:

24690 4096