蓝桥练习

1.核桃的数量

----最小公倍数问题

#include <iostream>
#include <cmath>
#include <algorithm>
using namespace std;
int lcm(int n,int m){
	int a,b,c;
	a=n;
	b=m;
	c=n%m;
	while(c!=0){
		n=m;
		m=c;
		c=n%m;
	}
	return a/m*b; 
}
int main(){
	int a,b,c;
	cin>>a>>b>>c;
	int ans=lcm(lcm(a,b),c);
	cout<<ans;
	return 0;
} 

2.打印十字图

----观察规律

解决方案

#include <iostream>
#include <cmath>
#include <algorithm>
#include <cstring>
using namespace std;
const int N=35;
char a[N][N]; 
bool  flag(int i,int j,int n){
	if(i>n*2+3)
		i=n*4+6-i;
	if(j>n*2+3)
		j=n*4+6-j;
	if(i<j) swap(i,j);
	if(i<=2&&j<=2) return false;
	if(i%2==1&&j>=i-2) return true;
	if(j%2==1&&j!=i-1) return true;
	return false;
}
int main(){
	int n;
	cin>>n;
	int k;
	k=9+(n-1)*4;
	for(int i=1;i<=k;i++){
		for(int j=1;j<=k;j++){
			if(flag(i,j,n)){
				cout<<'$';
			}
			else cout<<'.';
		}
		cout<<endl;
	}
	return 0;
}

3.称重问题

--DFS算法解决

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

例如:
用户输入:
5
程序输出:
9-3-1
用户输入:
19
程序输出:
27-9+1
要求程序输出的组合总是大数在前小数在后。
可以假设用户的输入的数字符合范围 1~121。

#include <iostream>
#include <fstream>
#include <vector>
using namespace std;
vector<int> v;
const int maxn = 30;
int n;
int a[5] = {1,3,9,27,81};

void dfs(int idx, int sum){
    if(sum == n){
        int len = v.size();
        cout<<v[0];
        for(int i = 1; i < len; ++i){
        	if(v[i]>0){
        		cout<<"+"<<v[i];
			}
            else cout<<v[i];
        }
    }
    if(idx < 0) return ;

    //0
    dfs(idx - 1, sum);

    //正+
    v.push_back(a[idx]);
    dfs(idx - 1, sum + a[idx]);
    v.pop_back();

    //负- 
    v.push_back(-a[idx]);
    dfs(idx - 1, sum - a[idx]);
    v.pop_back();
}

int main(){

    cin >> n;
    dfs(4, 0);

    return 0;
} 

4.一个句子中单词数量的统计,中间以空格隔开

---复习map的使用和strtok的分割使用

#include <iostream>
#include <fstream>
#include <vector>
#include <map>
#include <cstring>
const int N=1010;
using namespace std;
int main(){
	char str[N];
	map<string,int> mp;
	vector<string> vec;
	gets(str);
	
//	cout<<str;
	char *sp=strtok(str," ");
    while(sp){
        vec.push_back(sp);
        sp=strtok(NULL," ");
    }
    vector<string>::iterator it;
    for(it=vec.begin();it!=vec.end();it++){
    	 mp[*it]++;
	}
	for(map<string,int>::iterator it2=mp.begin();it2!=mp.end();it2++){
		cout<<it2->first<<" "<<it2->second<<endl;
	}
} 

5.等差等比数列公式

#include <iostream>
#include <cmath>
const int N=1010;
using namespace std;
int main(){
	long n,m;
	n=pow(2,20);
	n=n-1;
	m=pow(2,19);
	cout<<n<<'/'<<m;
} 

6.星期一

整个20世纪(1901年1月1日至2000年12月31日之间),一共有多少个星期一?

-----计算所有的天数,然后除以周7;

#include <iostream>
#include <fstream>
#include <vector>
#include <map>
#include <cstring>
#include <cmath>
const int N=1010;
using namespace std;
bool isleap(int year){
	return(year % 4==0&&year %100 != 0)||(year%400==0);
}
int main(){
	int num;
	for(int i=1901;i<=2000;i++){
		if(isleap(i)){
			num+=366;
		}
		else num+=365;
	}
	num=num/7;
	cout<<num;
} 

7.第几个幸运数

到x星球旅行的游客都被发给一个整数,作为游客编号。
x星的国王有个怪癖,他只喜欢数字3,5和7。
国王规定,游客的编号如果只含有因子:3,5,7,就可以获得一份奖品。

我们来看前10个幸运数字是:
3 5 7 9 15 21 25 27 35 45
因而第11个幸运数字是:49

小明领到了一个幸运数字 59084709587505,他去领奖的时候,人家要求他准确地说出这是第几个幸运数字,否则领不到奖品。

请你帮小明计算一下,59084709587505是第几个幸运数字。
----------

在从小到大的排序数组中,

lower_bound( begin,end,num):从数组的begin位置到end-1位置二分查找第一个大于或等于num的数字,找到返回该数字的地址,不存在则返回end。通过返回的地址减去起始地址begin,得到找到数字在数组中的下标。

upper_bound( begin,end,num):从数组的begin位置到end-1位置二分查找第一个大于num的数字,找到返回该数字的地址,不存在则返回end。通过返回的地址减去起始地址begin,得到找到数字在数组中的下标。
 

const long long mmx=59084709587505;
int main(){
	set<long long>ss;
	int a[3]={3,5,7};
	long long t=1;
	while(1){
		for(int i=0;i<3;i++){
			long long at=t*a[i];
			if(at<=mmx) ss.insert(at);
		}
		t=*ss.upper_bound(t);
		if(t==mmx){
			break;
		}
	}
	cout<<ss.size();
} 

8.航班时间

3
17:48:19 21:57:24
11:05:18 15:14:23
17:21:07 00:31:46 (+1)
23:02:41 16:13:20 (+1)
10:19:19 20:41:24
22:19:04 16:41:09 (+1)

#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <cstring>
#include <cmath>
using namespace std;
void printFormat( int b, char c) {
	if( b<10) printf( "0%d%c", b, c);
	else printf(  "%d%c", b, c);
}
int main(){
	int n;char c;
	scanf("%d",&n);
	int flytime[n];
	int t=2*n;
	while(t--){
		if(t%2){
			flytime[t/2]=0;
		}
		int h1,m1,s1,h2,m2,s2;
		scanf("%d:%d:%d %d:%d:%d",&h1,&m1,&s1,&h2,&m2,&s2);
		flytime[t/2]+=(h2-h1)*60*60+(m2-m1)*60+(s2-s1);
		while((c=getchar())!='\n'){
			if( c=='+') flytime[t/2] += 24*60*60*(getchar()-'0');
		}
	}
	for(int i=n-1;i>=0;i--){
		flytime[i]/=2;
		printFormat(flytime[i]/3600,':');
		printFormat(flytime[i]/60%60,':');
		printFormat(flytime[i]%60,'\n');
	}
}

9.星系炸弹

在X星系的广袤空间中漂浮着许多X星人造“炸弹”,用来作为宇宙中的路标。
每个炸弹都可以设定多少天之后爆炸。
比如:阿尔法炸弹2015年1月1日放置,定时为15天,则它在2015年1月16日爆炸。
有一个贝塔炸弹,2014年11月9日放置,定时为1000天,请你计算它爆炸的准确日期。
请填写该日期,格式为 yyyy-mm-dd  即4位年份2位月份2位日期。比如:2015-02-19
请严格按照格式书写。不能出现其它文字或符号。

//复习一下日期的计算操作

#include <iostream>
#include <cstring>
#include <algorithm>
#include <vector>
#include <set>
using namespace std;
bool isleap(int year){
	return ((year%4==0&&year%100!=0)||(year%400==0)) ;
}
int month[13][2]={0,0,31,31,28,29,31,31,30,30,31,31,30,30,31,31,31,31,30,30,31,31,30,30,31,31
};
int main(){
	int y,m,d,pause;
	cin>>y>>m>>d;
	cin>>pause;
	while(pause--){
		d++;
		if(d==month[m][isleap(y)]+1){
			m++;
			d=1;
		}
		if(m==13){
			y++;
			m=1;
		}
	}
	cout<<y<<'-';
	if(m/10==0){
		cout<<'0'<<m<<'-';
	}
	else cout<<m<<'-';
	if(d/10==0){
		cout<<'0'<<d;
	}
	else cout<<d;
}

10. 奇妙的数字


小明发现了一个奇妙的数字。它的平方和立方正好把0~9的10个数字每个用且只用了一次。
你能猜出这个数字是多少吗?请填写该数字,不要填写任何多余的内容。

//分析开始的时候,应该是平方占四位,立方占六位,立方 从47开始才是五位数(计算器能算出来),然后就开始枚举好了

//每一次枚举之后,要清空重新开始计算,不然累加就很大 找不到正确结果。(调bug好久 ,气死了)

#include <iostream>
#include <cstring>
#include <algorithm>
#include <vector>
#include <set>//自动去重
using namespace std;
int a[10]={0};//标记0到9这10个数用过的次数
set<int> match;
int main(){
	int two,three;
	for(int i=47;i<100;i++){
		int n=4,m=6;
		two=i*i;
		three=i*i*i;
		while(n--){
			int temp1=two%10;
			a[temp1]++;
			two=two/10;
		}
		while(m--){
			int temp2=three%10;
			a[temp2]++;
			three=three/10;
		}
		for(int j=0;j<10;j++){
			match.insert(a[j]);
		}
		if(match.size()==1) cout<<i;//为1则说明所有的数字都只用过一次
		match.clear();
		for(int j=0;j<10;j++){
			a[j]=0;
		}
	}

}

 11. 牌型种数


小明被劫持到X赌城,被迫与其他3人玩牌。
一副扑克牌(去掉大小王牌,共52张),均匀发给4个人,每个人13张。
这时,小明脑子里突然冒出一个问题:
如果不考虑花色,只考虑点数,也不考虑自己得到的牌的先后顺序,自己手里能拿到的初始牌型组合一共有多少种呢?
请填写该整数,不要填写任何多余的内容或说明文字
 

#include <iostream>
#include <algorithm>
using namespace std;
int ans=0;
void dfs(int r,int c){//r是每一种牌数,c是这种牌取几张 
	if(r>13) return ;
	if(c>=13){
		if(c==13){
			ans++;
		}
		return ;
	}
	dfs(r+1,c);
	dfs(r+1,c+1);
	dfs(r+1,c+2);
	dfs(r+1,c+3);
	dfs(r+1,c+4);
}
int main(){
	dfs(0,0);
	cout<<ans;
}

12.猜算式 

看下面的算式: 
□□ x □□ = □□ x □□□ 
它表示:两个两位数相乘等于一个两位数乘以一个三位数。 
如果没有限定条件,这样的例子很多。 
但目前的限定是:这9个方块,表示1~9的9个数字,不包含0。 
该算式中1至9的每个数字出现且只出现一次! 
比如: 
46 x 79 = 23 x 158 
54 x 69 = 27 x 138 
54 x 93 = 27 x 186 
….. 
请编程,输出所有可能的情况! 
注意: 
左边的两个乘数交换算同一方案,不要重复输出! 
不同方案的输出顺序不重要
//深搜进行查找,去重用set记录每一个查找到结果 的值,如果之前出现过就不输出,否则进行输出

#include <iostream>
#include <algorithm>
#include <set>
using namespace std;
int a[10];
set <int> s;
bool flag[10]={false};
void dfs(int step){
	if(step==10){
		int temp=(a[5]*10+a[6])*(a[7]*100+a[8]*10+a[9]);
		if((a[1]*10+a[2])*(a[3]*10+a[4])==temp){
			set<int>::iterator it;
			for(it=s.begin();it!=s.end();it++){
				if(*it==temp) return ;}
			s.insert(temp);
			cout<<(a[1]*10+a[2])<<"×"<<(a[3]*10+a[4])<<"="<<(a[5]*10+a[6])<<"×"<<(a[7]*100+a[8]*10+a[9])<<endl;		
		}
		return;
	}
	for(int i=1;i<10;i++){
		if(flag[i]==false){
			flag[i]=true;
			a[step]=i;
			dfs(step+1);
			flag[i]=false;
		}
	}
}
int main(){
	dfs(1);
}

13.等差素数列 

2,3,5,7,11,13,....是素数序列。
类似:7,37,67,97,127,157 这样完全由素数组成的等差数列,叫等差素数数列。
上边的数列公差为30,长度为6。

2004年,格林与华人陶哲轩合作证明了:存在任意长度的素数等差数列。
这是数论领域一项惊人的成果!

有这一理论为基础,请你借助手中的计算机,满怀信心地搜索:

长度为10的等差素数列,其公差最小值是多少?

//暴力解法__循环再循环再循环

#include <iostream>
#include <algorithm>
#include <set>
#include <queue>
#include <cstring>
#define MAX 100000
using namespace  std;
int table[MAX];//存储素数表 
bool flag[MAX]={false};//标记10000以内 ,素数为false,不是为true 
int ans=0;
int main(){
	for(int i=2;i<MAX;i++){//打印素数表 
		if(flag[i]==false){
			table[ans++]=i;
			for(int j=i+i;j<MAX;j+=i){
				flag[j]=true;
			}
		}
	}
	for(int i=0;i<ans;i++){//素数挨个循环 
		for(int j=1;j<1000;j++){//假设差为1到1000逐个遍历 
			int temp=table[i];
			int c=1;
			for(int step=1;step<10;step++){//十步以内 
				if(flag[temp+j]==true) {//有一个不是素数就退出循环 
					c=0;
					break;
				}
				else temp+=j;//是就下一步 再判断 
			}
			if(c==1){
				cout<<j;
				return 0;
			}
		}
	}
}

14.承压计算

X星球的高科技实验室中整齐地堆放着某批珍贵金属原料。

每块金属原料的外形、尺寸完全一致,但重量不同。
金属材料被严格地堆放成金字塔形。

                             7 
                            5 8 
                           7 8 8 
                          9 2 7 2 
                         8 1 4 9 1 
                        8 1 8 8 4 1 
                       7 9 6 1 4 5 4 
                      5 6 5 5 6 9 5 6 
                     5 5 4 7 9 3 5 5 1 
                    7 5 7 9 7 4 7 3 3 1 
                   4 6 4 5 5 8 8 3 2 4 3 
                  1 1 3 3 1 6 6 5 5 4 4 2 
                 9 9 9 2 1 9 1 9 2 9 5 7 9 
                4 3 3 7 7 9 3 6 1 3 8 8 3 7 
               3 6 8 1 5 3 9 5 8 3 8 1 8 3 3 
              8 3 2 3 3 5 5 8 5 4 2 8 6 7 6 9 
             8 1 8 1 8 4 6 2 2 1 7 9 4 2 3 3 4 
            2 8 4 2 2 9 9 2 8 3 4 9 6 3 9 4 6 9 
           7 9 7 4 9 7 6 6 2 8 9 4 1 8 1 7 2 1 6 
          9 2 8 6 4 2 7 9 5 4 1 2 5 1 7 3 9 8 3 3 
         5 2 1 6 7 9 3 2 8 9 5 5 6 6 6 2 1 8 7 9 9 
        6 7 1 8 8 7 5 3 6 5 4 7 3 4 6 7 8 1 3 2 7 4 
       2 2 6 3 5 3 4 9 2 4 5 7 6 6 3 2 7 2 4 8 5 5 4 
      7 4 4 5 8 3 3 8 1 8 6 3 2 1 6 2 6 4 6 3 8 2 9 6 
     1 2 4 1 3 3 5 3 4 9 6 3 8 6 5 9 1 5 3 2 6 8 8 5 3 
    2 2 7 9 3 3 2 8 6 9 8 4 4 9 5 8 2 6 3 4 8 4 9 3 8 8 
   7 7 7 9 7 5 2 7 9 2 5 1 9 2 6 5 3 9 3 5 7 3 5 4 2 8 9 
  7 7 6 6 8 7 5 5 8 2 4 7 7 4 7 2 6 9 2 1 8 2 9 8 5 7 3 6 
 5 9 4 5 5 7 5 5 6 3 5 3 9 5 8 9 5 4 1 2 6 1 4 3 5 3 2 4 1 
X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X 

其中的数字代表金属块的重量(计量单位较大)。
最下一层的X代表30台极高精度的电子秤。

假设每块原料的重量都十分精确地平均落在下方的两个金属块上,
最后,所有的金属块的重量都严格精确地平分落在最底层的电子秤上。
电子秤的计量单位很小,所以显示的数字很大。

工作人员发现,其中读数最小的电子秤的示数为:2086458231
请你推算出:读数最大的电子秤的示数为多少?

注意:需要提交的是一个整数,不要填写任何多余的内容

结合图看//如一部分图进行观察

#include <iostream>
#include <algorithm>
#include <set>
#include <queue>
#include <cstring>
#define MAX 100000
using namespace  std;
double map[32][32]={0}; 
int main(){
	for(int i=0;i<29;i++){
		for(int j=0;j<=i;j++){
			cin>>map[i][j];
		}
	}
	for(int i=0;i<30;i++){
		for(int j=0;j<=i;j++){
			map[i][j]+=(map[i-1][j]/2);//每一排第一列加上上一排的二分之一 
			if(j-1>=0){
				map[i][j]+=(map[i-1][j-1]/2);//每一排第一列以外 还要加上前一排前一列的二分之一 
			}
		}
	}
//	for(int i=0;i<30;i++){
//		cout<<map[29][i]<<" ";
//	}
	double a[30];
	for(int i=0;i<30;i++){
		a[i]=map[29][i];
	}
	sort(a,a+30);
	printf("%lf\n",(2086458231*a[29]/a[0]));
}

15.日期问题

小明正在整理一批历史文献。这些历史文献中出现了很多日期。小明知道这些日期都在1960年1月1日至2059年12月31日。令小明头疼的是,这些日期采用的格式非常不统一,有采用年/月/日的,有采用月/日/年的,还有采用日/月/年的。更加麻烦的是,年份也都省略了前两位,使得文献上的一个日期,存在很多可能的日期与其对应。  

比如02/03/04,可能是2002年03月04日、2004年02月03日或2004年03月02日。  

给出一个文献上的日期,你能帮助小明判断有哪些可能的日期对其对应吗?

输入
----
一个日期,格式是"AA/BB/CC"。  (0 <= A, B, C <= 9)  

输出
----
输出若干个不相同的日期,每个日期一行,格式是"yyyy-MM-dd"。多个日期按从早到晚排列。  

样例输入
----
02/03/04  

样例输出
----
2002-03-04  
2004-02-03  
2004-03-02  

资源约定:
峰值内存消耗(含虚拟机) < 256M
CPU消耗  < 1000ms
 

#include <iostream>
#include <algorithm>
#include <set>
#include <queue>
#include <cstring>
#define MAX 100000
using namespace  std;
bool isleap(int n){
	return (n%4==0&&n%100!=0)||(n%400==0);
}
int month[13][2]={{0,0},{31,31},{28,29},{31,31},{30,30},{31,31},{30,30},{31,31},{31,31},{30,30},{31,31},{30,30},{31,31}};
set<int> box;//自动去重和排列日期 
void islegal(int y,int m,int d){
	if(m>=13)	return;//月份超过返回 
	if(y<1960||y>2059) return;//年份超过返回 
	if(d<=month[m][isleap(y)]){//日期是否小于该年该月的天数 
	//	cout<<y*10000+m*100+d<<endl;
		box.insert(y*10000+m*100+d);
	
	}
}
void format(int number){//输出格式化 
	int yy=number/10000; cout<<yy<<'-';
	int mm=number/100%100;
	if(mm<10){
		cout<<'0'<<mm<<'-';
	}
	else cout<<mm<<'-';
	int dd=number%100;
	if(dd<10){
		cout<<'0'<<dd;
	}
	else cout<<dd;
	cout<<endl;
}
int main(){
	int a,b,c;
	scanf("%d/%d/%d",&a,&b,&c);
	islegal(1900+a,b,c);
	islegal(2000+a,b,c);
	islegal(1900+c,a,b);
	islegal(2000+c,a,b);
	islegal(1900+c,b,a);
	islegal(2000+c,b,a);
	set <int>::iterator it;
	for(it=box.begin();it!=box.end();it++){
		format(*it);
	}	
}

16. 包子凑数

小明几乎每天早晨都会在一家包子铺吃早餐。他发现这家包子铺有N种蒸笼,其中第i种蒸笼恰好能放Ai个包子。每种蒸笼都有非常多笼,可以认为是无限笼。

每当有顾客想买X个包子,卖包子的大叔就会迅速选出若干笼包子来,使得这若干笼中恰好一共有X个包子。比如一共有3种蒸笼,分别能放3、4和5个包子。当顾客想买11个包子时,大叔就会选2笼3个的再加1笼5个的(也可能选出1笼3个的再加2笼4个的)。

当然有时包子大叔无论如何也凑不出顾客想买的数量。比如一共有3种蒸笼,分别能放4、5和6个包子。而顾客想买7个包子时,大叔就凑不出来了。

小明想知道一共有多少种数目是包子大叔凑不出来的。

输入
----
第一行包含一个整数N。(1 <= N <= 100)
以下N行每行包含一个整数Ai。(1 <= Ai <= 100)  

输出
----
一个整数代表答案。如果凑不出的数目有无限多个,输出INF。

例如,
输入:
2  
4  
5   

程序应该输出:
6  

再例如,
输入:
2  
4  
6    

程序应该输出:
INF

样例解释:
对于样例1,凑不出的数目包括:1, 2, 3, 6, 7, 11。  
对于样例2,所有奇数都凑不出来,所以有无限多个。 
 

#include <iostream>
#include <algorithm>
#include <set>
#include <queue>
#include <cstring>
#define MAX 10010
using namespace  std;
int flag[MAX]={false};
int  a[MAX];
int ans=0;
int gcb(int a,int b){//找最大公约数
	if(b==0) return a;
	else return gcb(b,a%b);
}
int main(){
	int n;
	cin>>n;
	int a[n];
	for(int i=0;i<n;i++){
		cin>>a[i];
	}
	sort(a,a+n);
	int temp=a[0];
	for(int i=0;i<n;i++){
		temp=gcb(temp,a[i]);
	}
	if(temp!=1){
		cout<<"INF"<<endl;
		return 0;
	}
	flag[0]=true;
	for(int i=0;i<n;i++){
		for(int j=0;j+a[i]<MAX;j++){//类似欧拉筛素数的方法 能凑到的标记为true
			if(flag[j]==true){
				flag[j+a[i]]=true;
			} 
		}
	}
	for(int i=0;i<MAX;i++){
		if(flag[i]==false) ans++;
	}
	cout<<ans;
}

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值