暴力暴力暴力 又简单到难
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;
}