gf5vjt_简单算法

Download Report

Transcript gf5vjt_简单算法

简单算法
基本算法
1、求最大公倍数
2、求n-m范围内的质数
3、约数求和
4、数字分离
5、统计字符出现个数
穷举法
例1:哥德巴赫是一个古老而著名的数学难题。就是任一充分大的偶数,可以
用两个素数之和表示。例如
4=2+2
6=3+3
8=3+5
98=19+79
它的理论证明很麻烦,现在我们对有限范围内的数,用计算机加以验证。
试编写程序,以实验数据写出实验结果。输入一个数n(n<=10000)
样例输入:98
样例输出:19+79
算法步骤:
1、读入数n;
2、穷举出i(2……(n-2));
3、若i为质数,n-i也为质数,则输出i,n-i;
否则跳回第2步;
穷举法
int main()
{
int i,j,k,n;
cin>>n;
for(i=2;i<=n-2;i++)
{
for(j=2;j<=sqrt(i)&& i%j!=0;j++);
if (j>=sqrt(i))
{
for(k=2;k<=sqrt(n-i)&& i%k!=0;k++);
if (k>=sqrt(n-i)) {cout<<i<<“+”<<k<<endl;return 0;}
}
}
}
穷举法
例2:阿姆斯特朗数:如果一个正整数等于其各个数字的立方和,则该数称为
阿姆斯特朗数(也称自恋数),如407=64+0+343,试编程求出
n(n<=10000)以内的所有阿姆斯特朗数。
算法步骤:涉及到分离数字
1、穷举出所有n以内的数,i=1…n
2、对任意i分离每位数字求立方和
3、判断是否相等,然后输出
穷举法
int main()
{
int a1,a2,a3,a4,a5,n,a;
cin>>n;
for(a=1;a<=n;a++)
{ a1=a%10;
a2=(a/10)%10;
a3=(a/100)%10;
a4=(a/1000)%10;
a5=a/10000;
if(a1*a1*a1+a2*a2*a2+a3*a3*a3+a4*a4*a4+a5*a5*a5==a)
cout<<a<<" ";
}
}
穷举法
例3:输出7和7的倍数,还有包含7的数字例如(17,27,37...70,71,
72,73...)
输入:一个整数N。(N不大于30000)
输出:从小到大排列的不大于N的与7有关的数字,每行一个。
样例输入:20
样例输出:
7
14
17
穷举法
int main()
{
int a1,a2,a3,a4,a5,n,a,f; //f为标志
cin>>n;
for(a=1;a<=n;a++)
{ f=0;
if(a%7==0) f=1;
if(f==0)
{a1=a%10;
a2=(a/10)%10;
a3=(a/100)%10;
a4=(a/1000)%10;
if(a1==7||a2==7||a3==7||a4==7) f=1;
}
if(f==1)cout<<a<<endl;
}
}
思考题
警察局抓了A、B、C、D四名偷窃嫌疑犯,其中一人是小偷。审问中,
A说“我不是小偷。”
B说“C是小偷。”
C说“小偷肯定是D”
D说“C在冤枉人”
现在已知4人中3人说的是真话,1人说的是假话,问到底谁是小偷?
穷举法
int main(){
int i,j,k,l;
for(i=0;i<2;i++)
for(j=0;j<2;j++)
for(k=0;k<2;k++)
for(l=0;l<2;l++)
if((i!=1)+(k==1)+(l==1)+(l!=1)==3&&i+j+k+l==1)
{ if(i==1) cout<<'A';
else if(j==1) cout<<'B';
else if (k==1) cout<<'C';
else cout<<'D';
}
cout<<" is thief";
}
递推法
例4:请编程输出该数列前20项。0,1,1,2,4,7,13,24,44,…
算法分析:f4=f1+f2+f3
f5=f2+f3+f4
……………..
递推式: fn=f(n-3)+f(n-2)+f(n-1)
递推法
int main()
{
int f1=0,f2=1,f3=1,f4,i;
for(i=1;i<=20;i++)
{ f4=f1+f2+f3;
cout<<f1<<',';
f1=f2;
f2=f3;
f3=f4;
}
}
递推法
例5:猴子吃桃问题。猴子摘了一堆桃,第一天吃了一半,还嫌不过瘾,又吃
了一个;第二天又吃了剩下的一半零一个;以后每天如此。到第n天,猴子
一看只剩下一个了。问最初有多少个桃子?
输入一个数n(n<=20)
输出最初的桃子个数
算法分析: 设第一天有x个桃子 即F(1)=x
F(2)=x/2-1
F(3)=F(2)/2-1;
…………………..
F(n-1)=F(n-2)/2-1;
F(n)=F(n-1)/2-1=1 再倒推回去 F(n-1)=2*(F(n)+1)
这种递推称为逆推
递推法
int main()
{
int n,i,s=1; //s表示第i天的桃子数,初值为第n天的
cin>>n;
for(i=n;i>0;i--)
s=(s+1)*2; //从n-1天开始逆推出第1天的桃子数
cout<<s;
}
递推法
例6:设有一头小母牛,从出生第四年起每年生一头小母牛,按此规律,第N
年时有几头母牛?
输入:一个整数N,独占一行。(1≤N≤50)
输出:一个整数(独占一行)表示第N年时母牛的数量
样例输入: 20
样例输出: 872
递推法
int main()
{
int a1,a2,a3,a4,i,n;
cin>>n;
a1=a2=a3=a4=1;
for(i=4;i<=n;i++)
{
a4=a1+a3;
a1=a2;
a2=a3;
a3=a4;
}
cout<<a4<<endl;
}
思考题
有一堆桃子和N只猴子,第一只猴子将桃子平均分成了M堆后,还
剩了1个,它吃了剩下的一个,并拿走一堆。后面的猴子也和第1只进行
了同样的做法,请问N只猴子进行了同样做法后这一堆桃子至少还剩了
多少个桃子(假设剩下的每堆中至少有一个桃子)?而最初时的那堆桃子
至少有多少个?
输入包含二个数据,数据间用空格隔开。第一个数据为猴子的只数
N(1≤N≤10),第二个数据为桃子分成的堆数M(2≤M≤7)。
输出包含两行数据,第一行数据为剩下的桃子数,第二行数据为原
来的桃子数。
样例输入:
32
样例输出:
1
15
int main()
{
long long n,m,i=n,k=1,s;
cin>>n>>m;
s=m-1;
while(i>=1)
{ i--;
if(s%(m-1)==0)
s=s/(m-1)*m+1;
else
{ k++;
s=k*(m-1);
i=0;}
}
cout<<k*(m-1)<<endl<<s;
}