C语言双重循环的几种用法
连续因子(PTA 7-4)
#include<stdio.h>
#include<math.h>
int prime (int n);
int main (void) {
int n;
scanf ("%d", &n);
int i, j, sqr, sum;
int max_len = 0;
int max_size = 0;
if (prime(n)) {
printf ("1\n%d\n", n);
}
else {
sqr = (int)sqrt( 1.0 * n );
for (i = 2; i <= sqr; i++){//寻找n的第一个因子
if (n % i == 0) {
sum = i;
for (j = i + 1; j <= sqr; j++) {//寻找最长连续因子序列
sum *= j;
if (n % sum != 0) break;
}
if(max_size < j - i){//更新最长因子序列
max_size = j - i;
max_len = i;
}
}
}
printf ("%d\n", max_size);
for (i = max_len; i <= max_len + max_size - 1; i++) {
if(i != max_len) printf("*");
printf("%d",i);
}
}
return 0;
}
int prime (int n) {
int i, sqr;
sqr = (int)sqrt( 1.0 * n);
if (n < 2) return 0;
for (i = 2; i <= sqr; i++){
if(n % i == 0) return 0;
}
return 1;
}
两个重点:
1.双重循环确定因子序列,运用max_len,max_size保存最大长度和该序列开始的位置,第一重循环确定因子,第二重循环确定长度
2.输出控制,第一个因子前不输出*
素因子分解(PTA 7-5)
/*双重循环的应用之素因子分解(PTA 7-5)*/
#include <stdio.h>
#include <math.h>
int prime (long int n);
int main (void) {
long int n;
scanf ("%ld", &n);
long int i, j, sqr, expn,count = 1;
if (n == 1) printf ("%ld", n);
sqr = (long int)sqrt(1.0 * n);
for ( i = 2; i <= sqr; i++) {
if (prime(i)) {//素数
if (n % i == 0){ //因子
if (count != 1) printf ("*");
printf ("%ld", i);
expn = 0;
count++;
while (n % i == 0){
expn++;
n = n / i;
}
if (expn > 1) printf ("^%ld", expn);
}
}
}
if (n > 1) printf ("%ld",n);
printf("\n");
return 0;
}
int prime (long int n) {
long int i, sqr;
if (n == 1) return 0;
sqr = (long int)sqrt(1.0 * n);
for (i = 2; i <= sqr; i++){
if (n % i == 0) return 0;
}
return 1;
}
也是两个重点
1.第一重循环确定因子,第二重循环确定系数
2.count及expn确定输出*和^
拼数字并排序(XDOJ)[字符串处理]
从一个连续的字符串中找到各个数字字符并将其转化为可用以计算的数值
问题描述:对于输入的字符串(只包含字母和数字),将其中的连续数字拼接成整数。
例如,字符串abc123d5e7f22k9
提取出 123 5 7 22 9
int i = 0,j,k = 0,ans = 0,count = 0;
for ( i = 0; str[i]!='\0' ; i++ ){
if ( str[i] >= '0' && str[i] <= '9' ){
count++;//记录位数
if ( str[i+1] > '9' || str[i+1] < '0' ){
for( j = i - count + 1; j <= i ; j++){
ans = ans*10 + str[j] - '0';
}
num[k++] = ans;
ans = 0;//置零!!
count = 0;//置零!!
}
}
}
运用一(用栈处理前缀表达式)
因为从右至左进栈,所以在处理字符串时表达略有不同,但思路是相同的。
for( i = strlen(str) - 1; i >= 0; i--){
int a,b;
//处理多位数
ans = 0;
if( str[i] >= '0' && str[i] <= '9'){
count++;
if( str[i-1] ==' '){
for( j = i ; j < i + count ; j++){
ans = ans * 10 + str[j] - '0';
}
Push(&S,ans);
count = 0;
ans = 0;
}
}
/*省略部分与栈相关的操作*/
}
暂时只碰到了这些类似的题目,后续会补充…
报数出列问题(约瑟夫变形)
题目描述:已知N个人(以编号1,2,3,…,N分别表示)排成一列, 第一轮从编号为1的人开始依次报数,数到2的倍数的人出列;第二轮从头开始依次报数,数到3的倍数的人出列;第三轮再次从头开始依次报数,数到2的倍数的人出列;第四轮从头开始依次报数,数到3的倍数的人出列;依此规律重复下去,直到队列中的人数不超过三个为止。要求输出此时队列中剩下的人在初始队列中的编号。
#include <stdio.h>
#define MAXSIZE 5005
int num[MAXSIZE];
int main (void) {
int n;
scanf ("%d", &n);
int i, count, temp;
temp = n;
//赋值
for (i = 1; i <= n; i++) {
num[i] = i;
}
//循环
while (temp > 3) {
count = 0;
for (i = 1; i <= n; i++){
if (num[i] == 0) continue;
else count++;//必须有else 否则continue会越过这句执行
if(count == 2) {
num[i] = 0;
count = 0;
}
}
temp -= temp / 2;
if (temp <= 3) break;
count = 0;
for (i = 1; i <= n; i++) {
if (num[i] == 0) continue;
else count++;
if (count == 3) {
num[i] = 0;
count = 0;
}
}
temp -= temp / 3;
}
for (i = 1; i <= n; i++) {
if (num[i]) printf ("%d ",num[i]);
}
printf ("\n");
return 0;
}
参考自士兵队列训练报数问题,我的另一篇文章报数出列也有提及。
一个比较巧妙的点是计数器count的使用。(约瑟夫应该也可以这样实现,后续来补坑)
另外一个比较巧妙的点就是把两轮报数看作一组来实现。
水仙花数的判断
/*水仙花数*/
#include<stdio.h>
#include<math.h>
int function (int a, int b);
int main (void) {
int a, b, count;
scanf ("%d %d", &a, &b);
count = function (a,b);
printf ("%d\n", count);
return 0;
}
int function (int a, int b) {
if (a < b && b < 100 || a > b && a < 100) return 0;
int count = 0, i, k, t, j = 0, temp;
double sum = 0, x, y;
int num[5];
if (a > b) {
t = a;
a = b;
b = t;
}
if (a < 100) {
for (k = 100; k <= b; k++){
temp = k;
while (temp) {
num[j] = temp % 10;
temp = temp / 10;
j++;
}
/*for (i = 0; i < j; i++) {
printf ("%d",num[i]);
}
printf ("\n");*/
for (i = 0; i < j; i++) {
x = num[i] * 1.0;
y = j * 1.0;
//printf ("%.0f %.0f\n", x, y);
sum += pow (x, y);
}
if (sum == k * 1.0) count++;
j = 0;
sum = 0;
}
}
else{
for (k = a; k <= b; k++){
temp = k;
while (temp) {
num[j] = temp % 10;
temp = temp / 10;
j++;
}
for (i = 0; i < j; i++) {
x = num[i] * 1.0;
y = j * 1.0;
sum += pow (x, y);
}
if (sum == k * 1.0) count++;
j = 0;
sum = 0;
}
}
return count;
}
双重循环中用到的计数器之类的变量要及时清零
找位置
(先占个坑)
字符串解压缩
对于字符串中连续出现的同一个英文字符,用该字符加上连续出现的次数来表示(连续出现次数小于3时不压缩)
请设计一个程序,将采用该压缩方法得到的字符串解压缩,还原出原字符串并输出。
输入说明
输入数据为一个字符串(长度不大于50,只包含字母和数字),表示压缩后的字符串
输出说明
在一行上输出解压缩后的英文字符串(长度不超过100),最后换行。
输入样例
a5b3aba13b4
输出样例
aaaaabbbabaaaaaaaaaaaaabbbb
for (i = 0; i < len; i++) {
if (str[i] >= '0' && str[i] <= '9') {
count++;
if (str[i + 1] < '0' || str[i + 1] >'9') {
for (j = i - count + 1; j <= i; j++) {
num = num * 10 + str[j] - '0';
}
ch = str[i - count];
for (k = 1; k < num; k++) {
printf ("%c", ch);
}
count = 0;
num = 0;
}
}
else {
printf ("%c", str[i]);
}
}
找数字的变形,在取数字的同时找到数字的前一个字符输出。