zoukankan      html  css  js  c++  java
  • 蓝桥杯之数学思维

    [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
    ",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
    ",x=gcd(a,b));	
    	printf("lcm:%d
    ",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);
    	
    }

  • 相关阅读:
    AGC037F Counting of Subarrays
    AGC025F Addition and Andition
    CF506C Mr. Kitayuta vs. Bamboos
    AGC032D Rotation Sort
    ARC101F Robots and Exits
    AGC032E Modulo Pairing
    CF559E Gerald and Path
    CF685C Optimal Point
    聊聊Mysql索引和redis跳表
    什么是线程安全
  • 原文地址:https://www.cnblogs.com/sctb/p/11919661.html
Copyright © 2011-2022 走看看