蓝桥杯练习——不定方程解法2021.2.23

蓝桥杯练习——不定方程解法

问题

对形如ax+by=c的不定方程求它的解

分析

一般会采用暴力破解的方法,即在给定数据区间内进行循环,然后找到符合条件的输出。但是这样要用到两重循环,对于数据体量大的情况解决效率很低

解决

ax+by=c

即:ax=c-by

只需要找到一个y满足c-by可以被a整除即可找到一个解,一重循环

1.从小到大尝试,求出一个特解:x0,y0

2.求通解:x=x0+at;y=y0-bt;t根据题目取值-1,-2,0 ,1,2,3等

代码

import java.util.Scanner;
/*
 * 求解:ax+by=c 
 * ax=c-by
 * */
public class MaiBuDao {
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		Scanner scanner=new Scanner(System.in);
		int a=scanner.nextInt();
		int b=scanner.nextInt();
		int c=scanner.nextInt();
		int x=0,y=0,i,t,x0=0,y0=0;
		for(i=0;i<=10000;i++) {
			if((c-b*i)%a==0) {
				y0=i;
				x0=(c-b*i)/a;
				break;
			}
		}
		for(t=0;t<=1000;t++) {
			x=x0+a*t;
			y=y0-b*t;
			System.out.println(x+" "+y);
		}
	}
}

延申

大部分题目不会简单的让求一个公式的解,更多的会变换一些方式。

比如有的题可能和不等式的解法这一个公式关系不大,主要是对原有的问题变换一种解题思路

例题——鲜花数

视频学习

问题

一个N位的十进制正整数 ,如果它的每个位上的数字的N次方的和等于这个数本身,则称其为花朵数。例如:
当N=3时, 153就满足条件,因为1^3 + 5^3 + 3^3 = 153 ,这样的数字也被称为水仙花数
(其中, “入”表示乘方, 5^3表示5的3次方,也就是立方) .
当N=4时, 1634满足条件,因为1^4 + 6^4 + 3^4 + 4^4= 1634.
当N=5时, 92727满足条件。
实际上,对N的每个取值,可能有多个数字满足条件。
程序的任务是 :求N最大为21时 ,所有满足条件的花朵数。 注意:当N=21时,这个整数有21位 ,它的各 个位数字的21次方之和正好等于这个数本身。
如果满足条件的数字不只有一个,请从小到大输出所有符合条件的数字,每个数字占-行。因为这个数字很大,请注意解法时间上的可行性。

【输入】一个整数N

【输出】所有满足的数

思路

这道题很像“水仙花数”,“玫瑰花数”,一般都是直接暴力破解。比如这样的:

public class RoseNum {
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		int i,j,x,sum=0;
		for(i=100;i<=999;i++) {
			j=i;
			while(j>0) {
				x=j%10;
				sum+=(x*x*x);
				j/=10;
			}
			if(sum==i) {
				System.out.println(i);
			}
			sum=0;
		}
	}
}

但是,如果幂的次数达到21的话直接循环肯定是行不通的

假如某个数是它各个位置上的和,那么如果将这数某两位交换位置也并不影响最后算出的总和。所以大致思路就是先算出0-9每个数的N次幂,存在一个数组baseBigIntegers中,对于每个数字数字的次数,用一个数组num来存储。

所有出现的数字的21次幂乘以出现次数算出总和,再看总和中每个数字出现的次数和原数每个数字出现次数比较,如果相等,则是所求答案。

baseBigIntegers数组:存放0-9的N次幂

num数组:0-9各出现几次

sumn数组:和的各位数字各出现几次

cal函数:用来计算0-9的N次幂

​ 其中,用到BigInteger类,这个类适用于体量非常大的大整数,常用方法.ONG置一,.ZERO置零,.valueOf()取得某数的数值,.multiply()乘,.add加。

fun函数:用来试探num数组的各位可以置成什么值

​ k代表当前进行到0-9中的哪个数,sum代表剩余名额。因为所有数字总共出现N次,所以每次从0-sum试探,而进入下一层递归的时候sun要减去已经置好的次数。

test函数:用来判断置的这一组值是否符合要求

代码

import java.math.BigInteger;
import java.util.Scanner;
public class Flowers {
	public static int N;
	public static BigInteger[] baseBigIntegers=new BigInteger[10]; //存放每个数字的21次方
	public static BigInteger cal(int n) {
		BigInteger aBigInteger=BigInteger.ONE;
		int i;
		for(i=0;i<N;i++) {
			aBigInteger=aBigInteger.multiply(BigInteger.valueOf(n));
		}
		return aBigInteger;
	}
	public static void test(int[] num) {
		int i;
		BigInteger sumnBigInteger=BigInteger.ZERO;
		for(i=0;i<num.length;i++) {
			sumnBigInteger=sumnBigInteger.add(baseBigIntegers[i].multiply(BigInteger.valueOf(num[i])));
		}       //算出总和
		String string=sumnBigInteger.toString();
		if(string.length()!=N)return;
		int sumn[]=new int[10];
		for(i=0;i<string.length();i++) {
			sumn[string.charAt(i)-'0']++;
		}
		for(i=0;i<10;i++) {     //两边次数相等即是答案
			if(sumn[i]!=num[i])return;
		}
		System.out.println(sumnBigInteger);
	}
	public static void fun(int[] num,int k,int sum) {
		int i;
		if(sum==0) {     //试探次数用完了
			test(num);
			return;
		}
		if(k==num.length-1) {     //试到最后一位,次数全是最后一位的
			num[k]=sum;
			test(num);
			return;
		}
		for(i=0;i<=sum;i++){    
			num[k]=i;         //先试试能否置成这个次数
			fun(num, k+1, sum-i);   //试探下一位,名额-用掉的
			num[k]=0;       //回溯
		}
	}
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		Scanner scanner=new Scanner(System.in);
		N=scanner.nextInt();
		//对0-9求21次方,存放在base数组中
		int i;
		for(i=0;i<baseBigIntegers.length;i++) {
			baseBigIntegers[i]=cal(i);
		}
		//定义一个数组num记录每个数字出现几次
		int []num=new int[10];
		//查找,fun函数,num[],进行到第几个k,还剩几个名额sum
		fun(num,0,N);
	}
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值