蓝桥杯之数学思维

[4.1 奇怪的捐赠]

地产大亨Q先生临终的遗愿是:拿出100万元给X社区的居民抽奖,以稍慰藉心中愧疚。
麻烦的是,他有个很奇怪的要求:
1. 100万元必须被正好分成若干份(不能剩余)。
  每份必须是7的若干次方元。
  比如:1元, 7元,49元,343元,...  
2. 相同金额的份数不能超过5份。
3. 在满足上述要求的情况下,分成的份数越多越好!

请你帮忙计算一下,最多可以分为多少份?

思路:
代码:
#include<cstdio>

int main(){
	
	int n=1000*1000;
	int re[100],a=0;
	
	while(n>0){
		re[a++]=n%7;
		n=n/7;
	}
	
	int sum;
	for(int i=0;i<a;i++){
		sum+=re[i];
	}
	
	printf("%d",sum);
	
}
------------------------------------------

[4.2 真题:天平称重]

用天平称重时,我们希望用尽可能少的砝码组合称出尽可能多的重量。
如果只有5个砝码,重量分别是1,3,9,27,81
则它们可以组合称出1到121之间任意整数重量(砝码允许放在左右两个盘中)。

本题目要求编程实现:对用户给定的重量,给出砝码组合方案。
例如:
用户输入:
5
程序输出:
9-3-1
用户输入:
19
程序输出:
27-9+1

要求程序输出的组合总是大数在前小数在后。
可以假设用户的输入的数字符合范围1~121

[4.2 模m运算]

思路:
某个数由3的倍数加减来表示,可以看成某个数的三进制表示,

代码:
#include<cstdio>
#include<cmath>

int main(){
	int n,a[100],k=0;
	scanf("%d",&n);
	
	while(n>0){
		int t=n%3;
		if(t==2){
			t=-1;
			n=n/3+1;
			a[k++]=t;
			continue;
		}
		a[k++]=t;
		n=n/3;
	}
	
	for(int i=k-1;i>=0;i--){
		int num=pow(3,i);
		
		if(i==k-1){
			printf("%d",num);
		}else{
			
			if(a[i]>0){
				printf("+%d",num);
			}
			if(a[i]==0){
				continue;
			}
			if(a[i]<0){
				printf("-%d",num);
			}			
		}
	}	
}

------------------------------------------

尼姆堆

有3堆硬币,分别是3,4,5
二人轮流取硬币。
每人每次只能从某一堆上取任意数量。
不能弃权。
取到最后一枚硬币的为赢家。

求先取硬币一方有无必胜的招法。

数论...同余理论

思路:

    0010
    0101
    1100
 2  1110
 --------
    0101


x ^ y ^ x = y


首先对所有数进行亦或,得到sum,然后将sum与每个数亦或,此时得到的数和另外所有数字亦或的结果一样,x ^ x = 0,如果这个数字比之前的数字小,就是合理的。

代码:
#include<cstdio>

void g(int a[],int len){
	int  sum=0;
	for(int i=0;i<len;i++){
		sum = sum ^ a[i];
	}
	
	for(int i=0;i<len;i++){
		int x=sum^a[i];
		if(x<a[i]){
			printf("%d --> %d\n",a[i],x);
		}
	}
}

int main(){
	int a[]={2,5,12,14};
	g(a,4);
	
} 
------------------------------------------

[4.3 因数分解]

关键:算数基本定理

质因数分解的唯一性

------------------------------------------

求最大公约数与最小公倍数

中国古代...辗转相除法
欧几里得定理:gcd(a,b) = gcd(b,a%b)

最小公倍数 = 乘积 / 最大公约数

代码:
#include<cstdio>

int gcd(int a,int b){	
	if(b==0) return a;
	return gcd(b,a%b);
}

int main(){
	int a,b,x;
	scanf("%d%d",&a,&b); 
	printf("gcd:%d\n",x=gcd(a,b));	
	printf("lcm:%d\n",a*b/x);
}
------------------------------------------

[4.4 真题:一步之遥]

从昏迷中醒来,小明发现自己被关在X星球的废矿车里。
矿车停在平直的废弃的轨道上。
他的面前是两个按钮,分别写着“F”和“B”。

小明突然记起来,这两个按钮可以控制矿车在轨道上前进和后退。
按F,会前进97米。按B会后退127米。
透过昏暗的灯光,小明看到自己前方1米远正好有个监控探头。
他必须设法使得矿车正好停在摄像头的下方,才有机会争取同伴的援助。
或许,通过多次操作F和B可以办到。

矿车上的动力已经不太足,黄色的警示灯在默默闪烁...
每次进行 F 或 B 操作都会消耗一定的能量。
小明飞快地计算,至少要多少次操作,才能把矿车准确地停在前方1米远的地方。

请填写为了达成目标,最少需要操作的次数。

扩展欧几里得定理:
Ax + By = gcd(A,B) 有解

思路:不是太明白

代码:
#include<cstdio>
#include<cmath>

int g(int a,int b,int arr[]){
	
	if(b==0){
		arr[0]=1;
		arr[1]=0;
		return a;
	}
	
	int ans = g(b,a%b,arr);
	int t=arr[0];
	arr[0]=arr[1];
	arr[1]=t - a/b * arr[0];
	
	return ans;
}


int main(){
	int a[2]={0};	
	g(97,127,a);	
	printf("%d",abs(a[0])+abs(a[1]));
	
}

实用版:
#include<cstdio>
#include<algorithm>
#include<cmath>
using namespace std;
int main(){
	int ans[100],k=0;
	for(int i=-1000;i<1000;i++){
		for(int j=-1000;j<1000;j++){
			if(97*i+127*j==1){
				ans[k++]=abs(i)+abs(j);
			}
		}
	}
	sort(ans,ans+k);
	printf("%d",ans[0]); 
}
------------------------------------------

[4.5 有理数运算]

------------------------------------------

[4.6 作业:素数表]

第1个素数是2,第2个素数是3,...
求第100002(十万零二)个素数

素数的筛法

思路:
使用循环,判断是否为素数,思路都非常简单,只是如果直接运算的话时间太长,我们进行优化:1、在判断素数的时候,可以将for(int i=2;i<k;i++)改为for(int i=2;i*i<=k;i++),因为一个合数至少可以分解成两个因数,其中一个因数一定小于等于它的开平方,此外,偶数一定不是素数,所以循环的时候,每步加2。

代码:
#include<cstdio>
#include<cmath>

int test(int k){
	for(int i=2;i*i<=k;i++){
		if(k%i==0){
			return 0;
		}
	}
	return 1;
}


int main(){
	
	int count=1,n=3;
	while(count!=100002){
		if(test(n)){
			count++;
		}
		
		n+=2;
	}
	
	printf("%d",n-2);
	
}

阅读更多
想对作者说点什么?

博主推荐

换一批

没有更多推荐了,返回首页