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;
}