1.9 while循环
1.9 while循环
while知识点
循环:如果条件为真,就一直执行,直到条件不为真
bool flag = true; //true, false, 1, 0
while(flag){
//循环体
}
//解释:如果满足flag为真,就执行循环体,直到flag不为真,退出
1. 输入 n, 输出 1~n
【题目描述】输入 n, 输出 1~n(1 2 3 4 5...n)。
#include<iostream>
using namespace std;
int main(){
int n, i=1; cin>>n;
while(i<=n){
cout<<i<<" ";
i++;
}
return 0;
}
2. 平均分
【题目描述】考试结束后,老师想计算全体学生的平均分,你能帮助老师吗?
现在无法知道参考人数,但是知道参加考试的人都不是 0 分。
所以,提供给你的若干个考试成绩,以 0 作为计算的结束标志。
输入样例:90 0
输出样例:90
输入样例:90 89 90 0
输出样例:89.6667
#include <iostream>
using namespace std;
int main() {
double score, sum=0, cnt=0; cin>>score;
while(score!=0) {
sum += score ;
cnt++;
cin>>score;
}
cout<<sum/cnt<<endl;
return 0;
}
3. 质数判断
【题目描述】判断给定的正整数 n(保证在 int 范围内)是否为质数,
如果 n 是质数,输出 yes; 否则,输出 no。
素数判定:如果 n(n>1) 能被 [2,n-1] 中某个整数整除,则证明n是合数,不是质数(素数)。
数学小知识:
0 是整数,但不是正整数;
1 既不是质数,也不是合数。
合数是指:大于 1, 且因子除了 1 和本身外,还有其余因子的数。
#include<cstdio>
int main() {
int i=2, n; scanf("%d", &n);
bool flag=1; // 假设 n是质数
for(int i=2; i<n; i++){ // i的取值范围 [2, n-1]
if(n%i==0){ // 证明是合数
flag=0; break;
}
}
if(flag==0) printf("no");
else if(n>=2) printf("yes");
return 0;
}
//-------------------------------------
#include<cstdio>
int main() {
int i=2, n; scanf("%d", &n);
bool flag=1; // 假设 n是质数
while(i<n) { // i的取值范围 [2, n-1]
if(n%i==0) {// 证明是合数
flag=0;
}
i++;
}
if(flag==0) printf("no");
else if(n>=2) printf("yes");
return 0;
}
4. 输入一个正整数,输出其位数
【题目描述】输入一个正整数,输出其位数
输入样例:123
输出样例:3
#include<iostream>
using namespace std;
int main(){
int n, ans=1;//这个数至少是一位数
cin>>n;
while(n>9){
n /= 10;//去掉个位数
ans++;
}
cout<<ans;
return 0;
}
5. 输入任意两个自然数,求他们的最大公约数
#include<iostream>
#include<algorithm>
using namespace std;
int main() {
int a,b; cin>>a>>b;
for(int i=min(a,b); i>=1; i--) {
if(a%i==0 && b%i==0) {
cout<<i; break;
}
}
return 0;
}
6. P1150 Peter的烟
【题目描述】Peter 有 n 根烟,他每吸完一根烟就把烟蒂保存起来,k(k>1)个烟蒂可以换一个新的烟,那么 Peter 最终能吸到多少根烟呢?吸烟有害健康。
输入格式:每组测试数据一行包括两个整数 n, k (1<n,k≤1e8)
输出格式:对于每组测试数据,输出一行包括一个整数表示最终烟的根数。
输入样例:4 3
输出样例:5
输入样例:10 3
输出样例:14
解析:由于烟蒂可以换新烟,所以我们的退出条件就是剩余烟蒂不足以换得一支新烟。
举例:n=10, k=3 的时候
当前一次吸烟数量:10 ,剩余烟蒂数量为:10
可换得 3 支烟,并剩余 1 支烟蒂,故而第二次可吸烟数量:3, 剩余烟蒂数量为:4
可换得 1 支烟, 故而第三次可吸烟数量:1,剩余烟蒂数量为:2
所以三次吸烟的总数为:10+3+1=14
10/3=3...1
4/3=1...1
2/3=0...2
#include<iostream>
using namespace std;
int main(){
int n,k; cin>>n>>k;
int all = n;// 吸烟数量
int now = n;// 现有烟蒂
while(now>=k){
all += now/k; // 吸烟总数 += 现有烟蒂可换新烟数量(now/k)
now = now/k +now%k;// 现有烟蒂 = 新换的烟的数量 + 不足以换一支烟的烟蒂数量
}
cout<<all;
return 0;
}
int main_2(){
int n,k; cin>>n>>k;
cout<<n+(n-1)/(k-1);//奥数题,解析见下
return 0;
}
注明:上述奥数解法来源洛谷,总之不是我写的,而且...我觉得这个思路一般...不会想到。
补充知识:最大公约数&最小公倍数
求最大公约数的三种方法:
1.最小递减法
先找a,b的最小值,判断该值能否同时被a,b整除,如果可以该数就是答案,否则每次-1,继续判断,直到找到答案。
两个数的最大公约数最小为 1。
#include<iostream>
using namespace std;
int main() {
int a,b; cin>>a>>b;
for(int i=min(a,b); i>=1; i--) {
if(a%i==0 && b%i==0) {// 满足 i 同时是 a,b 的约数的情况
cout<<i; break; //因为是从大到下枚举的,所以找到的第一个数就是最大公约数
}
}
return 0;
}
2.更相减损法
a-b=c,则 a,b 的最大公约数就是 b,c 的最大公约数,如果 c=0(即a=b),a 就是答案。
#include<iostream>
using namespace std;
int main() {
int a,b;
cin>>a>>b;
while(a!=b) {
//更相减损术需要考虑到两个数的大小,所以多了交换的步骤
if(a<b){ int t=a; a=b; b= t; }
int c = a-b;
a = b;
b = c;
}
cout<<a;
return 0;
}
3.辗转相除法
a/b=q...r,则 a,b 的最大公约数就是 b,r 的最大公约数,如果 r=0, 则 b 就是答案(或者说如果 b=0,则 a 就是答案)。
#include<iostream>
using namespace std;
int main() {
int a,b;
cin>>a>>b;
while(b!=0) {
int r = a%b;
a = b;
b = r;
}
cout<<a;
return 0;
}
求最小公倍数的两种方法:
1.最大递增法
原理:两个数的最小公倍数一定大于等于这两个数的最大值
先找a,b的最大值,判断该值能否同时整除a,b,如果可以该数就是答案,否则每次+1,继续判断,直到找到答案。
#include<iostream>
using namespace std;
int main() {
int a,b; cin>>a>>b;
for(int i=max(a,b); ; i++) {//死循环,直到找到答案才 break
if(i%a==0 && i%b==0) {// 如果 i能同时整除 a,b,则证明 i是 a,b的公倍数
cout<<i; break;//由于是从公倍数的最小可能答案开始枚举,所以找到的第一个答案就是最小公倍数,就可以break了
}
}
return 0;
}
2.定理法
原理:两个数的乘积等于这两个数的最大公约数与最小公倍数的乘积。
#include<iostream>
using namespace std;
int main() {
int a,b; cin>>a>>b;
int x=a, y=b;//用定理法求最小公倍数,则原数需要记录
while(b!=0) {//辗转相除法求最大公约数
int r=a%b;
a = b;
b = r;
}
int max_G = a;//最大公约数
int min_G = x*y/max_G;//最小公倍数
cout<<"最大公约数:"<<max_G<<endl;
cout<<"最小公倍数:"<<min_G<<endl;
return 0;
}
具体证明过程如下: