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