蓝桥杯算法提高 连接乘积(完全c语言版)

蓝桥杯算法提高 连接乘积(完全c语言版)

资源限制
时间限制:1.0s 内存限制:256.0MB
问题描述
  192这个数很厉害,用它分别乘以1、2、3,会得到:
  192 x 1 = 192
  192 x 2 = 384
  192 x 3 = 576
  把这三个乘积连起来,得到192384576,正好是一个1~9的全排列
  我们把上面的运算定义为连接乘积:
  m x (1 … n) = k(其中m > 0 且 n > 1,对于上例,m = 192、n = 3、k = 192384576)
  即k是把m分别乘以1到n的乘积连接起来得到的,则称k为m和n的连接乘积。
  按字典序输出所有不同的连接乘积k,满足k是1~9的全排列
输出格式
  每个k占一行
样例输出
显然,结果中应包含一行:
192384576

#include<stdio.h>
#include<math.h>
long long t[20]={0};//t要在排序函数里用,就放在外面了 
void quicksort(int left,int right)//排序数组,递归快速排序 
{
	int i,j,k;
	long long temp,m;
	i=left;
	j=right;
	temp=t[i];//选出枢纽元,储存在temp中 
	if(left>right)
	return;//跳出递归的关键
	while(i<j)
	{
	while(t[j]>temp&&i<j)//从右边开始扫描
		j--;
	while(t[i]<temp&&i<j)//从左边开始扫描
		i++;
	if(i<j)
	{
	m=t[i];
	t[i]=t[j];
	t[j]=m;
	}//将数值交换
	}
	quicksort(left,i-1);//调用自身
	quicksort(i+1,right);
}

int jingwei(int a[]){//进位函数 
	int i=0;
	int t=0;
	int temp;
	while(1){
	temp=a[i];//保存当前位的值 
	a[i]=a[i]%10+t;//当前位的值等于当前位求余+上一位的进位 
	t=temp/10;//进位等于当前位/10 
	i++;//游标后移 
	if(t==0&&a[i]==0&&a[i-1]==0&&a[i+1]==0&&a[i+2]==0){//这里比较暴力,因为中间最多就3个0,所以也没想就直接乱写一通 
		break; 
	}	
	}
	return i-1;//返回的i-1是存放数据的最后一个位置 
}
int check(int a[]){//检查m是否到达最大值 
	if(a[0]==6&&a[1]==7&&a[2]==8&&a[3]==9/*&&a[4]==5&&a[5]==6&&a[6]==7&&a[7]==8&&a[8]==9*/)
    //这里是表示m(a[])的遍历终点,因为n(kum)最小为2,所以k最大肯定是一个四位数和一个五位数的组合 
	//比如9999 19998,这里就举个例子这个显然不符合条件
	//但是可以推断m(a[])最大就是9999,但是m里面肯定不能有重复的数,9999里面有多个9,所以暂且判断最大是9876 
	return 0;
    else 
    return 1;
}
int main(){
	int m[10]={0};//存放m 
	int n[10]={0};//存放n 
	int k[10]={0};//存放k 
	int i,j,l,p,r=0,s=0;//全是游标 
	int tum=1,num=0,kum=0;
	while(check(m)==1){//大循环开始 
	m[0]=m[0]+1;//每次给个位+1 
	i=jingwei(m);//调用进位函数调整数m组并返回i为最后一个存放位置 
	/*for(p=i-1;p>=0;p--)
	printf("%d ",m[p]);
	printf("\n"); 
	printf("**i=%d**\n",i);*/
	/*for(j=0;j<9;i++){
		printf("%d",m[j]);
	}*///查bug 
	//printf("\n");
	tum=1;
	s=0;
	/*for(p=i-1;p>=0;p--)
	printf("*%d",m[p]);
	printf("\n");*///查bug 
	while(1){//小循环1开始 
		for(j=0;j<9;j++){
    	n[j]=0;//n数组反复利用,怕出问题写了这个 
	}
	for(j=0;j<=i-1;j++){
		n[j]=m[j]*tum;//将m数组的0-i位依次乘tum 放进n数组里,tum的范围是2-9 	
	}
	l=jingwei(n);//进位函数 ,返回调整后的数组的存值的最后一个位置 
	/*
	for(p=9;p>=0;p--)
	printf("%d ",n[p]);
	printf("\n"); *///查bug 
	l=jingwei(n); //调用进位函数调整数n组并返回l为最后一个存放位置
	/*for(p=l-1;p>=0;p--)
	printf("%d",n[p]);
	printf("\n"); *///查bug 
	for(p=l-1;p>=0;p--){
	  k[s]=n[p];//把数组n的值给数组k 
	  s++;//k数组的游标,游标s是没有重置的会一直加	
	}
	tum++;
	if(tum==10||s>=9)//如果k数组的存放到9位数或者n已经加到9了就跳出循环就跳出循环 
	break;	//这里其实考虑到一开始其实k是到不了9位的	
	}//小循环1结束 
	/*for(p=0;p<=8;p++)
	printf("%d ",k[p]);
	printf("\n");*///查bug 
num=0;
for(i=1;i<=9;i++){//判断k数组里面是否有1-9
	for(j=0;j<9;j++){
	  if(k[j]==i&&k[j]!=0){
	  	num++;
	  	break;//防止重复计数,如果没break,9个1其实num还是能加到9 
	  }
	  	
	}
}
if(num==9&&s==9){//如果1-9都在k里而且s恰好等于9就是符合条件的了
//这里注意s==9是必须的,因为之前s其实是可以加到>9的
//比如k数组里本来是134578 269156但是只取9位就break了,变成了134578269是不符合条件的,但是由于我的算法原因,会判定为变成符合条件,所以我加了s==9来解决这个问题 
	for(i=0;i<9;i++){//后面的就很简单了,就是取数组元素转成十进制数,然后排个序输出 
	  t[r]=t[r]+k[i]*pow(10,8-i);
	}
r++;	
}

	}//大循环结尾 
	quicksort(0,r-1);//排序 
for(i=0;i<r;i++)
printf("%lld\n",t[i]);
	return 0;
}

c语言没有string所以我感觉写起来挺麻烦,但是有个同学问了我用c怎么写,我其实也是个菜鸡,就用死办法写了一个,其实还可以优化的是m ( a[] )遍历的时候如果有重复元素的可以直接给m加一跳过这个循环,其实可以快得多,一开始怕超时写了一个判断重复的函数,但是有点小bug所以没加进去,但是这样还是可以通过的,官网上cpu利用的数据居然是0,通过率是100
之后还会用c++或者java写一个,简易一些

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值