包子凑数问题

文章讨论了一个编程问题,通过计算蒸笼中包子数量的最大公因数来确定能否凑出特定数量的包子,涉及数学模型和素数特性。
摘要由CSDN通过智能技术生成

#include <stdio.h>
int gcd(int,int);
int main()
{
  int n,zhenglong[200]={0},max_gcd;//zhenglong数组记录每一种蒸笼能够容纳多少个包子,max_gcd变量用来记录最大公因子。
  int pick[1000000]={0};//pick数组就是顾客想要的包子的个数,0代表凑不出,1代表凑得出。
  int count=0;//记录共有多少种数目是凑不出来的
  scanf("%d",&n);
  for(int i=0;i<n;i++){
    scanf("%d",&zhenglong[i]);
  }
  //简单来说,这道题的数学模型就是多元一次方程ax+by+cz+...=C,输入的每个蒸笼里的包子数目看成a,b,c......,只要能
  //找到非负x,y,z......能够凑到C,就代表包子大叔能凑到C个数量的包子。数学定理:如果a,b,c......都是两两互为素数的,
  //则用来凑出C的x,y,z......(也就是方程的解)有无穷多个,且凑不出来C的个数是有限个。
  //素数具有最大公因子是1的特点,只需要看a,b,c......的最大公因子是不是1就可以判断凑不出C的个数有限还是无限。
  //如果最大公因子是1,说明方程解有无穷多个,凑不出的个数就有限;如果最大公因子不是1,说明方程无解,凑不出的个数就无穷多个了。
  for(int i=0;i<n;i++){
    if(i==0||i==1){
      max_gcd=gcd(zhenglong[0],zhenglong[1]);
    }
    max_gcd=gcd(max_gcd,zhenglong[i]);
  }
  if(max_gcd!=1){//最大公因子不等于1,凑不出的个数是无穷多个
    printf("INF");
  }else{
    //else内部代码块一定是凑不出来的个数是有限的这种情况,接下来就是要找出所有凑不出来的C以及数目。
    //注意:对于ax+by+cz+......=C方程,C=0能凑出来,则C+a,C+b,C+c........(C=0)也能凑出来。
    //同样:对于ax+by+cz+......=C方程,C+a能凑出来,把C+a记作X,则X+a,X+b,X+c........(X=C+a)也能凑出来。
    //依次搜索记录所有可以凑出的C即可。
    for(int i=0;i<n;i++){//遍历所有蒸笼下的包子个数,zhenglong[i]即所谓的a,b,c......
      for(int C=0;C+zhenglong[i]<100000;C++){
      //C是所有顾客可能想要的包子个数,C+zhenglong[i]代表上面的C+a,C+b,C+c......或者X+a,X+b,X+c......
      //由于凑不出的个数是有限的,这里的上限取得大一点就可以了,比如100000
        if(C==0){
        pick[0]=1;//C为0也就是顾客想要买的数量是0的时候,这种情况是一定可以凑出来的,只要x,y,z......全部取0就可以了。
        }
        if(pick[C]){//如果C能凑出来
          pick[C+zhenglong[i]]=1;//那么C+zhenglong[i]也一定能凑出来
        }
      }
    }
    for(int i=0;i<100000;i++){
      if(pick[i]==0){
        count++;
      }
    }
    printf("%d",count);
  }
  return 0;
}
int gcd(int a,int b){//求两个数的最大公因子(即最大公约数)的函数
  return b?gcd(b,a%b):a;//递归实现
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值