1,简单的暴力*: 何为暴力?:就是从小到大每次枚举了每个数字,如果遇到满足的解,就输出;这就叫做枚举暴力;
-eg.给定m,n,请问有多少个鸡和多少个兔,m是腿数,n是总数;输出鸡的数量和兔的数量; input:m=36 ,n=11 output:4 7
#include <iostream> using namespace std; int main() { int m,n,i,j;//i表示鸡,j表示兔 cin>>m>>n; for(i=0;i<=n;++i) { for(j=0;j<=n;++j) { if((2*i+4*j==m)&&(i+j==n))//满足条件就输出,然后break掉 { cout<<i<<" "<<j<<endl; break; } } } }优化的方法:该代码调用调用了2层循环,复杂度为n*n; 只要数据大了时间就变大了,所以我们可以简化代码,这个就可以化简代码时间和缩小规模: **这题我们发现有一个i就可以用n-i表示兔子;
#include <iostream> using namespace std; int main() { int m,n,i,j;//i表示鸡,j表示兔 cin>>m>>n; for(i=0;i<=n;++i) { if(i*2+(n-i)*4==m) { cout<<i<<' '<<n-i; break; } } }这个叫剪枝,就是当数据比较大的时候,就把一些已经超过了明显不可能的情况直接退出,简少代码运行量 大家一定听过蓝桥杯的“暴力搜索简枝” 2.最大乘积 输入n个元素组成序列s,找出一个乘积最大的序列,使得该序列最大 input: 3 2 4 -3 5 2 5 -1 2 -1 ouput: 8 20
#include <iostream> using namespace std; int main() { int n,ans,max,b,a; while(cin>>n) { cin>>b; max=b; ans=b; for(int i=1;i<n;++i) { cin>>a; ans*=a; if(ans>max) { max=ans; } } cout<<max<<endl; } }这边可以看为每次输入一组数据就计算,每次一计算就直接比较大小,大于就更新。 3.分数拆分: 输入正整数k,找到所有的正整数x>=y 比如2 1/2=1/6+1/3; 1/2=1/4+1/4; 我们一开始会直接想一步步枚举,遇到可以的情况就输出 那么如何枚举呢,从什么到什么呢?似乎没有思路。 但是我们从表达式入手发现x《=y 那么1/x>=1/y即是1/k>=2/y; 那么y就<=2*k; 每次枚举就好了
注意分数和浮点数的加减乘除 1.因为浮点数在计算机里面是小数不精确的存储,所以不能用等于比较,那么要比较的话只能通分来得简单: 比如1/k=1/x+1/y; 通分变为xy=ky+k*x;
#include<iostream> using namespace std; int main() { int k, x, y; while (cin >> k) { for (y = k + 1; y <= 2 * k; y++) { x = k*y / (y - k);//通过题目的等式很容易推出来的 if (k*y % (y - k) == 0)//计算x是不是整数,是整数就判断出来输出 { if (x >= y) cout << "1" << "/" << k << "=" << "1" << "/" << x << "+" << "1" << "/" << y << endl; } } } return 0; }这里有2个小技巧, 1.通过通分来计算可以避免分数的不确定比较; 2,这里x是整数,所以我们要判断x是不是整数;
如果一个正整数n至少在两种不同的进制下b1和b2下都是回文数(2<=b1,b2<=10),则称n是双基回文数(注意,回文数不能包含前导零)。输入正整数S<10^6,输出比S大的最小的双基回文数。 输入: 1600000 输出: 1632995 从头到尾巴 开始一个个枚举如果可以的话就输出 这里要写成2个函数一个是写成下一个进制的函数,一个是判断是否是回文。 回文和函数都设为数组不用数字的话就比较好比较;
/* 1.从下一个开始枚举; 2. 如果满足2个不同进制是回文就输出: 3.回文用数组来进行 */ #include <iostream> using namespace std; int a[30]; bool huiwen(int a[],int n)//从头到尾巴2边到中间进行比较,如果不对就返回false 不然就返回true; { for(int i=0;i<=n/2;++i) { if(a[i]!=a[n-i]) return false; } return true; } bool converse(int n,int k) /*把十进制的n转化为k进制*/ { int flag=0,j=0,i; while(n)生成一个数组n进制的 { a[j++]=n%k; n/=k; } if(huiwen(a,j-1)) { flag=1;//如果是回文数,flag设为1; } if(flag) { return true; } else return false; } int main() { int i,j,k,n,cnt; while(scanf("%d",&n)!=EOF) { for(j=n+1;;j++) { int p=0; for(i=2,cnt=0;i<=10;i++) { if(converse(j,i)) cnt++; /*记录回文次数*/ if(cnt>=2) /*是双基回文数*/ { p=1; break; } } if(p) { printf("%d\n",j); break; } } } return 0; }