1.啤酒和饮料
啤酒每罐2.3元,饮料每罐1.9元。小明买了若干啤酒和饮料,一共花了82.3元。
我们还知道他买的啤酒比饮料的数量少,请你计算他买了几罐啤酒。
思路:循环遍历,注意精度问题,将钱数乘10计算。
答案:11
用浮点数计算时有误差不能直接用==号来判断,可以通过控制误差来得到,在进行验算;
或者直接将价格,以及花的钱提高十倍,都化为整数计算;
//思路:循环遍历,注意精度问题,将钱数乘10计算。
#include <iostream>
#include <cmath>
using namespace std;
int main(){
for(int i = 0; i <= (int)82.3/2.3; i++){
sum = 0;
for(int j = 1; j <= (int)82.3/1.9; j++){
if(abs(i * 2.3 + j * 1.9 - 82.3) < 0.0001){ //这里不能直接用==来判断,有误差!!!
cout << i << " " << j << endl;
cout << 11 * 2.3 + 30 * 1.9 << endl;
return 0;
}
}
}
return 0;
}
#include <iostream>
using namespace std;
int main(){
for(int i = 0; i < 40; ++i){
for(int j = 1; j < 43; ++j){
if(i > j)continue;
if(i * 23 + j * 19 == 823){
cout<<i<<" "<<j<<endl;
}
}
}
return 0;
}
2.李白打酒
话说大诗人李白,一生好饮。幸好他从不开车。
一天,他提着酒壶,从家里出来,酒壶中有酒2斗。他边走边唱:
无事街上走,提壶去打酒。
逢店加一倍,遇花喝一斗。
这一路上,他一共遇到店5次,遇到花10次,已知最后一次遇到的是花,他正好把酒喝光了。
请你计算李白遇到店和花的次序,可以把遇店记为a,遇花记为b。则:babaabbabbabbbb 就是合理的次序。像这样的答案一共有多少呢?请你计算出所有可能方案的个数(包含题目给出的)。
思路:dfs
答案:14
#include <bits/stdc++.h>
using namespace std;
int ct;
void dfs(string str, int d, int h, int sum){ //还需要遇到的次数:店家,花,剩余的酒
if(sum < 1 || d < 0 || h < 0){
return ;
}
if(d == 0 && h == 0 && sum == 1){
ct++;
cout << str << endl;
return ;
}
dfs(str + "a", d - 1, h, 2 * sum);
dfs(str + "b", d, h - 1, sum - 1);
}
int main(){
string s;
dfs(s, 5, 9, 2); //最后一次遇到花,相当于遇到花九次,剩余1升的酒;
cout << ct << endl;
return 0;
}
3.切面条
一根高筋拉面,中间切一刀,可以得到2根面条。
如果先对折1次,中间切一刀,可以得到3根面条。
如果连续对折2次,中间切一刀,可以得到5根面条。
那么,连续对折10次,中间切一刀,会得到多少面条呢?
思路:
由于对折次数仅为10,数据规模并不大,可以通过手算简单的完成。
对折0次,得到2根;
对折1次,得到2 * 2 - 1 = 3
对折2次,得到3 * 2 - 1 = 5
对折3次,得到5 * 2 - 1 = 9
对折4次,得到9 * 2 - 1 = 17
对折5次,得到17 * 2 - 1 = 33
对折6次,得到33 * 2 - 1 = 65
对折7次,得到65 * 2 - 1 = 129
对折8次,得到129 * 2 - 1 = 257
对折9次,得到257 * 2 - 1 = 513
对折10次,得到513 * 2 - 1 = 1025
其实,上面的思路就是一种递归,可以把这种思想通过代码实现。
递归有基本递归与尾递归两种形式,本文分别进行了代码实现。
尾递归在一定程度上可以提高程序效率,通常比基本递归多一个参数。
递归的本质就是栈,当然可以用栈实现,在数据规模特别大的时候要显式的使用栈,以防止栈溢出。
答案:1025
思路:就是找规律,会发现所得的片段是对折折横的个数加上2.找个纸片看看。
而折痕的规律是,上一次得到的折痕加上上一次的层数为此次的折痕数,层数为:2的n-1次方,故折痕为: 1 + 2 + 4 + 8 + 16 + 2的9次方
最后加上2即可。
#include <iostream>
#include <sstream>
using namespace std;
int main(){
int n;
int sum = 1;
int q = 1;
for(int i = 1; i <= 9; i++){
q *= 2;
sum += q;
cout << q << " ";
}
cout << endl;
cout << sum + 2 << endl;
return 0;
}
史丰收速算
史丰收速算法的革命性贡献是:从高位算起,预测进位。不需要九九表,彻底颠覆了传统手算!
速算的核心基础是:1位数乘以多位数的乘法。
其中,乘以7是最复杂的,就以它为例。
因为,1/7 是个循环小数:0.142857...,如果多位数超过 142857...,就要进1
同理,2/7, 3/7, ... 6/7 也都是类似的循环小数,多位数超过 n/7,就要进n
下面的程序模拟了史丰收速算法中乘以7的运算过程。
乘以 7 的个位规律是:偶数乘以2,奇数乘以2再加5,都只取个位。
乘以 7 的进位规律是:
满 142857... 进1,
满 285714... 进2,
满 428571... 进3,
满 571428... 进4,
满 714285... 进5,
满 857142... 进6
请分析程序流程,填写划线部分缺少的代码。
答案:if(r>0)return i
-
- //计算个位
- int ge_wei(int a)
- {
- if(a % 2 == 0)
- return (a * 2) % 10;
- else
- return (a * 2 + 5) % 10;
- }
- //计算进位
- int jin_wei(char* p)
- {
- char* level[] = {
- "142857",
- "285714",
- "428571",
- "571428",
- "714285",
- "857142"
- };
- char buf[7];
- buf[6] = '\0';
- strncpy(buf,p,6);
- int i;
- for(i=5; i>=0; i--){
- int r = strcmp(level[i], buf);
- if(r<0) return i+1;
- while(r==0){
- p += 6;
- strncpy(buf,p,6);
- r = strcmp(level[i], buf);
- if(r<0) return i+1;
- ______________________________; //填空
- }
- }
- return 0;
- }
- //多位数乘以7
- void f(char* s)
- {
- int head = jin_wei(s);
- if(head > 0) printf("%d", head);
- char* p = s;
- while(*p){
- int a = (*p-'0');
- int x = (ge_wei(a) + jin_wei(p+1)) % 10;
- printf("%d",x);
- p++;
- }
- printf("\n");
- }
- int main()
- {
- f("428571428571");
- f("34553834937543");
- return 0;
- }
5.打印图形
小明在X星球的城堡中发现了如下图形和文字:
rank=3
*
* *
* *
* * * *
rank=5
*
* *
* *
* * * *
* *
* * * *
* * * *
* * * * * * * *
* *
* * * *
* * * *
* * * * * * * *
* * * *
* * * * * * * *
* * * * * * * *
* * * * * * * * * * * * * * * *
ran=6
*
* *
* *
* * * *
* *
* * * *
* * * *
* * * * * * * *
* *
* * * *
* * * *
* * * * * * * *
* * * *
* * * * * * * *
* * * * * * * *
* * * * * * * * * * * * * * * *
* *
* * * *
* * * *
* * * * * * * *
* * * *
* * * * * * * *
* * * * * * * *
* * * * * * * * * * * * * * * *
* * * *
* * * * * * * *
* * * * * * * *
* * * * * * * * * * * * * * * *
* * * * * * * *
* * * * * * * * * * * * * * * *
* * * * * * * * * * * * * * * *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
小明开动脑筋,编写了如下的程序,实现该图形的打印。
答案:f(a,rank-1,row, col + w/2)
//思路:就是先初始化一个矩阵,然后递归填值,每次递归下去都是在一个小矩阵中填值,每次固定的是
//矩阵的左上角,一次递归层数以及左上角坐标,注意没行的星号间是由空格的!!
#include <iostream>
#include <cstdio>
using namespace std;
#define N 70
void f(char a[][N], int rank, int row, int col)
{
if(rank==1){
a[row][col] = '*';
return;
}
int w = 1;
int i;
for(i=0; i<rank-1; i++)
w *= 2;
f(a, rank-1, row, col + w / 2) ;//填空 //最后一行是32 * 2个。故1/4 为 w/2
f(a, rank-1, row+w/2, col);
f(a, rank-1, row+w/2, col+w);
}
int main()
{
char a[N][N];
int i,j;
for(i=0;i<N;i++)
for(j=0;j<N;j++)
a[i][j] = ' ';
f(a,6,0,0);
for(i=0; i<N; i++){
for(j=0; j<N; j++)
printf("%c",a[i][j]);
printf("\n");
}
return 0;
}
7.六角填数
如图所示六角形中,填入1~12的数字。
使得每条直线上的数字之和都相同。
图中,已经替你填好了3个数字,请你计算星号位置所代表的数字是多少?
思路:dfs
答案:10
#include <iostream>
#include <cmath>
#include <cstdio>
#include <cstring>
using namespace std;
#define eps 10e-10
#define N 15
int a[N];
bool vis[N];
void dfs(int x){
if(x == 1 || x == 2 || x == 12){
dfs(x+1);
return ;
}
if(x > 12){
int t[6];
t[0] = a[1] + a[3] + a[6] + a[8];
t[1] = a[1] + a[4] + a[7] + a[11];
t[2] = a[2] + a[3] + a[4] + a[5];
t[3] = a[2] + a[6] + a[9] + a[12];
t[4] = a[8] + a[9] + a[10] + a[11];
t[5] = a[12] + a[10] + a[7] + a[5];
for(int i = 1; i < 6; ++i){
if(t[i] != t[i-1])return ;
}
cout<<a[6]<<endl;
return ;
}
for(int i = 1;i < 13; ++i){
if(!vis[i]){
vis[i] = 1;
a[x] = i;
dfs(x+1);
vis[i] = 0;
}
}
}
int main(){
memset(vis,0,sizeof(vis));
vis[1] = 1;
a[1] = 1;
vis[8] = 1;
a[2] = 8;
vis[3] = 1;
a[12] =3;
dfs(1);
return 0;
}
暴力:
#include <iostream>
#include <algorithm>
using namespace std;
int a[9] = {2, 4, 5, 6, 7, 9, 10, 11, 12};
int x = 1, y = 3, z = 8;
int main()
{
do{
int d[10];
d[0] = 1 + a[0] + a[3] + a[5];
d[1] = 1 + a[1] + a[4] + a[8];
d[2] = 8 + a[0] + a[1] + a[2];
d[3] = 8 + a[3] + a[6] + 3;
d[4] = a[5] + a[6] + a[7] + a[8];
d[5] = 3 + a[7] + a[4] + a[2];
int flag = 0;
for(int i = 1; i <= 5; i++){
if(d[i] != d[0]){
flag = 1;
break;
}
}
if(!flag)
break;
}while(next_permutation(a, a + 9));
cout << a[3] << endl;
return 0;
}