C++ 统计由给定两个数字x和y组成的数字的数量,其中数字的和仅包含给定的数字x和y

C++ 统计由给定两个数字x和y组成的数字的数量,其中数字的和仅包含给定的数字x和y

问题声明包括统计由给定的两个数字x和y组成的尺寸为N的数字的数量,其中数字的和仅包含给定的数字x和y。

我们需要统计可以由x和y组成的不同数字的数量,这些数字将是尺寸为N的用户输入,其中N的范围为1到10^6。输入还会提供N的值。由尺寸为N的数字x和y组成的数字必须满足所形成数字的数字总和仅包含数字x和y。

由于N的值可能非常大,数字的数量可能非常大,所以我们需要返回以模1000000007 (即1e9+7)取余的答案。

以下示例更好地解释了该问题。

输入

x=4 , y=2  , N=2

输出

1

解释 - 这里给出的输入是x=4,y=2和N=2,这意味着我们需要找到包含2位数字的数字的数量。数字应该只是4和2,而且数字的位数的和应该只包含数字4和2。

满足条件的唯一可能数字是22。它包含2位数字,并由给定的数字组成,数字的位数之和等于4,即和只包含给定的数字。因此,对于此输入,答案为1。

输入

x=1 , y=3 , N=5

输出结果

15

解释 - 我们需要找到由数字1和3组成的大小为5的数字的计数,使得它们的数字之和只包含给定的数字。这样的数字可以是33331、33313、33133、31333、13333、33311、33113、31133、11333、13331、13313、13133、31313、31331、33131。

让我们了解一下找到使用给定数字形成的数字的计数的算法,使得它们的数字之和只包含给定的数字。

算法

给定的N的值很大,因此不可能检查每个可能的数字,以确定这些数字的数字之和是否只包含给定的数字。由于我们只需要计算由x和y组成的大小为N的数字的数量,我们只需要检查数字重复的次数。

假设x在数字中出现i次,那么y就会在数字中出现(N-i)次,因为数字仅由x和y构成,而数字的位数为N。因此,数字之和将为(x * i +(N-i)* y)。 **

如果和只包含x和y,那么我们可以使用组合数学找到使用i次x和(N-i)次y形成的数字的数量。

可以使用以下公式找到数字的计数:

$\mathrm{^NC_{i}=\frac{N!}{(N−i)!i!}or:factorial(N)modInverse(N−i)*modInverse(i)}$

该算法可以分为三个部分实现:

  • 为了检查数字中x重复的可能次数

我们可以使用一个for循环从i=0到i<=N进行迭代,其中N是考虑数字中x重复的可能情况的所需大小。

我们可以使用公式(xi + (N-i)y)来检查每种情况下数字的和,其中i是数字中x重复的次数,范围为[0,N]。

  • 检查数字的和是否只包含x和y作为其数字

由于使用x和y数字形成的数字的总和可以通过以下方法计算:

sum=(xi + (N-i)y) ,其中i是数字中x出现的次数,(N-i)表示数字中y出现的次数。

我们将创建一个函数来检查数字的总和。在函数中,我们将使用while循环迭代,直到总和变为0,并使用取余运算符检查总和的每个数字。

总和模10将给出数字的最后一位,因此我们将检查数字的最后一位是否等于x或y。如果最后一位等于x或y,我们将只需将数字除以10,以检查下一个数字,直到总和变为0。如果总和的每个数字都是x或y,我们将返回true。如果数字的任何一位不等于x或y,我们将返回false。

  • 如果总和只由x和y组成,找出用i次x数字形成数字的方法数量

在检查N个位数的数字中x出现i次的每个可能值时,如果由i次x数字和(N-i)次y数字形成的数字的位数只有x和y,则我们将使用组合学计算方法计算使用i次x数字和(N-i)次y数字形成不同数字的方法数量。

寻找组成不同数字的数字中将i次x个数字排列的方式的公式是\mathrm{^NC_{i}=\frac{N!}{(N-i)!*i!}}。由于\mathrm{^NC_{i}=^NC_{N-i}},因此我们可以计算其中任意一个。

\mathrm{^NC_{i}=factorial}

为了计算这种方式的数量,我们将预先计算阶乘和倒数阶乘的值,从0到最大值N,即10^6,并将其存储在大小为10^6+1的数组中。

可以使用以下公式计算modInverse:

modInverse(N!)= modInverse((N+1)!)*(N+1).

由于我们拥有可能的每个阶乘数值,我们将使用上述公式计算方式的数量。阶乘值可能很大,因此我们将将值存储在1e9+7的模数中。

我们将会计算使用特定数量的数字可以形成的不同数字的方式,并将它们加入答案中,进一步检查每个可能的数字位数并计算数字的数量。

我们可以使用这个算法找到由给定N个数字组成的数字的数量,这些数字的各个位数之和仅由给定数字组成。为了解决问题,我们将在我们的方法中使用这个算法。

方法

我们在实现该算法以找到数字数量的方法中需要遵循以下步骤:

  • 我们将创建一个函数来计算使用给定数字组成的数字数量,使得数字的各位数字之和只包含给定的数字。

  • 我们将在一个循环中迭代从i=0到i<=N,以检查每个由i个x数字和(N−i)个y数字组成的数字。

  • 如果由i个x数字和(N−i)个y数字组成的数字的各位数字之和只包含x和y,我们将使用公式\mathrm{^NC_{i}}计算形成N位数字的i个x数字的不同数量。

示例

//function to count the number formed by given digits whose sum having the given digit
#include <bits/stdc++.h>

using namespace std;

const int n=1000001;

const int mod=1e9+7;

//initialising array to store values of factorial and inverseFactorial till n
int fac[n]={0};
int inverseFac[n]={0};

//to calculate the inverse factorial of the last index
int lastFactorialIndex(int n,int m)
{
  int p=m;
  int a=1,b=0;
  if(m==1)
  {
      return 0;
  }
    while(n>1)
    {
      int quotient=n/m;

      int temp=m;

      m=n%m;

      n=temp;
      temp=b;

      b=a-quotient*b;

      a=temp;
    }

    if(a<0)
    {
     a=a+p; 
    }
    return a;

}

//function to store the values of factorial in the array
void factorial()
{
   fac[0]=1;

   fac[1]=1;

   for(int i=2;i<n;i++)
   {
       //since n!=n*(n-1)!
       fac[i]=(long long)fac[i-1]*i%mod;
   }


}

//function to calculate the inverse factorials for all values till n
void inverseFactorial()
{
    inverseFac[0]=1;
    inverseFac[1]=1;
    //calling the function to calculate the inverse factorial of last index
    inverseFac[n-1]=lastFactorialIndex(fac[n-1],mod);

    for(int i=n-2;i>=2;i--)
    {
        //inverse(i!)=inverse((i+1)!)*(i+1)
       inverseFac[i]=((long long)inverseFac[i+1]*(long long)(i+1)) % mod; 
    }
}

//function to check if the sum has only digits x and y
bool cal(int sum,int x,int y)
{

    if(sum==0)
    {
      return false;  
    }

    while(sum>0)
    {
        if((sum%10)!=x && (sum%10)!=y) //checking each digit of the number
        {
         return false;   
        }
        sum=sum/10;
    }
    return true;
}

//function give the number of ways of distinct numbers can be formed using i times x digit
long long int combinatorics(int n,int r)
{
    //using the formula nCr= factorial(n) * modInverse(n-r)*modInverse(r) % mod
 long long int ways= (long long)fac[n]*(long long)inverseFac[r] %mod *(long long)inverseFac[n-r]%mod;

  return ways;
}

// function to calculate count of numbers
int count_numbers(int m,int x,int y)
{
    //if both the digits are equal
    if(x==y)
    {
        if(cal(m*x,x,y)==true){
           return 1; 
        }
        else{
        return 0;
        }
    }
    int count=0;
    for(int i=0;i<=m;i++)
    {
        if(cal(i*x + (m-i)*y,x,y)) //checking for each possible case of x digit appearing i times
        {
           //if sum has the digits x and y, calculate the number of ways
            count = (count + combinatorics(m,i)) % mod; 
        }

    }
    return count;
}

int main()
{
    //calling the function to pregenerate factorials and inverse factorials
factorial();
inverseFactorial();

int m=188;
int x=8;
int y=4;
cout<<count_numbers(m,x,y);

return 0;
}

输出结果

917113677

时间复杂度 − O(n*logn)

空间复杂度 − O(n),因为我们使用了大小为n的数组来存储阶乘和倒数阶乘的值。

结论

本文讨论了使用给定的两个数字可以生成多少个数字的问题,使得数字的数字之和仅包含数字x和y。我们使用组合数学原理来确定数字的总数,而不是逐个检查每个数字。详细解释了有效的C++解决方案。

读完这篇文章后,希望你对这个问题和解决方案有了更好的理解。

Camera课程

Python教程

Java教程

Web教程

数据库教程

图形图像教程

办公软件教程

Linux教程

计算机教程

大数据教程

开发工具教程