一、全排列
从n个不同元素中任取m(m≤n)个元素,按照一定的顺序排列起来,叫做从n个不同元素中取出m个元素的一个排列。当m=n时所有的排列情况叫全排列。
交换法:全排序以‘123’为例,全排列就是从第一个数字起每个数分别与它后面的数字交换。i表示递归次数,k表示固定数字位数,后面的数字进行交换。当k等于数组长度时输出,返回递归过程并恢复交换。
代码如下:
#include<stdio.h>
#include<string.h>
void swap(char *a, char *b)
{
char temp;
temp = *a;
*a = *b;
*b = temp;
}
void fullPermutation(char *str, int k, int len) // k表示当前固定数字个数
{
int i;
if(k == len)
{
for(int j = 0; j <= len; j++)
printf("%c", str[j]);
printf("\n");
}
else
for(i = k; i <= len; i++)
{
//若数组有元素相同,则定义一个比较函数和此处if控制语句
swap(str + i, str + k);
fullPermutation(str, k + 1, len);
swap(str + i, str + k);
}
}
int main()
{
char str[10];
scanf("%s", str);
fullPermutation(str, 0, strlen(str)-1);
return 0;
}
填数法:将输出1到n分解为输出以1、2、3等为开头的全排列,设一个数组array和散列数组hashTable,假设当前已经填好了前index个数字,正准备填下一个数字,需要枚举hashTable数组中未填入的数字。
#include<cstdio>
const int maxn = 11;
int n, P[maxn], hashTable[maxn] = {false};
void generateP(int index){
//边界
if(index == n+1){
for(int i = 1; i <= n; i++){
printf("%d", P[i]);
}
printf("\n");
return;
}
for(int x = 1; x <= n; x++){
if(hashTable[x] == false){
P[index] = x;
hashTable[x] = true;
generateP(index+1);
hashTable[x] = false;
}
}
}
int main(){
n = 4;
generateP(1);
return 0;
}
二、进制转换
进制转换是人们利用符号来计数的方法。进制转换由一组数码符号和两个基本因素“基数”与“位权”构成。基数是指进位计数制中所采用的数码(数制中用来表示“量”的符号)的个数。位权是指进位制中每一固定位置对应的单位值。
- 将p进制数x转换为十进制数y
int y = 0,product = 1;
while(x != 0)
{
y = y + (x % 10)*product; //(x%10)获取个位数
x = x / 10; //去掉个位数
product = product * p;
}
- 将十进制数y转换为Q进制数
int array[111];
int num = 0;//余数的位数
do{
array[num++] = y%q;//除基取余
y /= q;
} while(y != 0) //当商不为0时进行循环
//注意逆序输出
三、最大公约数与最小公倍数
1.最大公约数
正整数 a 与 b 的最大公约数是 a 和 b所有公约数中最大的那个公约数,一般用 gcd(a, b) 来表示,常用欧几里得算法。(即辗转相除法)
/* 辗转相除法
a,b均为正整数,gcd(a, b) = gcd(b, a % b)
证明a = kb + r, a % b = (kb + r) % b, a % b = r % b
*/
#include<stdio.h>
int gcd(int a, int b)
{
if(b == 0)
return a;
else
return gcd(b, a % b);
}
int main()
{
int a, b;
while(scanf("%d%d", &a, &b) != EOF)
{
printf("%d\n", gcd(a, b));
}
return 0;
}
2.最小公倍数
正整数 a 和 b 的所有公倍数中最小的公倍数。最小公倍数的求解在最大公约数的基础上,即ab/gcd(a, b)。为防止ab在计算中溢出,可以采用a/gcd(a, b)*b。
#include<stdio.h>
int gcd(int a, int b)
{
if(b == 0)
return a;
else
return gcd(b, a % b);
}
int main()
{
int a, b;
while(scanf("%d%d", &a, &b) != EOF)
{
printf("%d\n", a/gcd(a, b)*b);
}
return 0;
}
四、分数
1.分数的表示
struct Fraction
{//分别为分子、分母
int up;
int down;
};
定义 Fraction 结构体类型表示分数,需要以下规则:
- 如果分母 down 为负数,那么令分子 up 和分母 down 都变为相反数。
- 如果分子 up 为 0,那么令分母 down为 1。
- 约分:求出分子绝对值与分母绝对值的最大公约数 gcd(up, down),然后令分子分母同时除以 gcd(up, down)。
//分数化简
Fraction reduction(Fraction result)
{
if(result.down < 0)
{
result.up = -result.up;
result.down = -result.down;
}
if(result.up == 0)
{
result.down = 1;
}
else
{
int d = gcd(result.up, result.down);
result.up /= d;
result.down /= d;
}
return result;
}
2.分数的四则运算
//分数加法
Fraction add(Fraction f1, Fraction f2)
{
Fraction result;
result.up = f1.up * f2.down + f2.up * f1.down;
result.down = f1.down * f2.down;
return reduction(result);
}
//分数减法
Fraction minu(Fraction f1, Fraction f2)
{
Fraction result;
result.up = f1.up * f2.down - f2.up * f1.down;
result.down = f1.down * f2.down;
return reduction(result);
}
//分数乘法
Fraction multi(Fraction f1, Fraction f2)
{
Fraction result;
result.up = f1.up * f2.up;
result.down = f1.down * f2.down;
return reduction(result);
}
//分数除法
Fraction divide(Fraction f1, Fraction f2)
{
Fraction result;
result.up = f1.up * f2.down;
result.down = f2.up * f1.down;
return reduction(result);
}
3.分数输出
分数输出需遵循以下规则:
- 输出分数前,需要对其进行化简
- 如果分数 r 的分母 down为 1,说明该分数是整数。
- 如果分数 r 的分子 up 的绝对值大于分母 down,说明改分数是假分数,应该以带分数的形式输出,即整数部分为 r.up / r.down,分子部分为 abs(r.up) % r.down,分母部分为 r.down。
#include<stdio.h>
#include<math.h>
struct Fraction
{
int up;
int down;
};
int gcd(int a, int b)
{
if(b == 0)
{
return a;
}
return gcd(b, a%b);
}
//分数化简
Fraction reduction(Fraction result)
{
if(result.down < 0)
{
result.up = -result.up;
result.down = -result.down;
}
if(result.up == 0)
{
result.down = 1;
}
else
{
int d = gcd(result.up, result.down);
result.up /= d;
result.down /= d;
}
return result;
}
//分数加法
Fraction add(Fraction f1, Fraction f2)
{
Fraction result;
result.up = f1.up * f2.down + f2.up * f1.down;
result.down = f1.down * f2.down;
return reduction(result);
}
//分数减法
Fraction minu(Fraction f1, Fraction f2)
{
Fraction result;
result.up = f1.up * f2.down - f2.up * f1.down;
result.down = f1.down * f2.down;
return reduction(result);
}
//分数乘法
Fraction multi(Fraction f1, Fraction f2)
{
Fraction result;
result.up = f1.up * f2.up;
result.down = f1.down * f2.down;
return reduction(result);
}
//分数除法
Fraction divide(Fraction f1, Fraction f2)
{
Fraction result;
result.up = f1.up * f2.down;
result.down = f2.up * f1.down;
return reduction(result);
}
//分数输出
void showFraction(Fraction r)
{
r = reduction(r);
if(r.down == 1)
printf("%d\n", r.up);
if(abs(r.up) > r.down)
printf("%d %d/%d\n", r.up/r.down, abs(r.up)%r.down, r.down);
else
printf("%d/%d\n", r.up, r.down);
}
int main(){
Fraction f1;
f1.up = 6;
f1.down = 4;
showFraction(f1);
return 0;
}
五、素数
/*
筛选法原理:如果 n 不是素数,那么 n 一定有小于 n 的素数因子,
那么一定会在枚举到 n 之前被筛选掉。
*/
#include<stdio.h>
const int maxn = 1000001;
int p[maxn] = {0};
int pNum = 0, prime[maxn];
void Find_Prime(int n)
{
for(int i = 2; i < maxn; i++)
{
if(p[i] == false)
{
prime[pNum++] = i;
if(pNum>=n) break;
for(int j = i*2 ; j < maxn; j += i)
{
p[j] = true;
}
}
}
}
int main()
{
//筛选法输出数组 m 到 n 之间的素数
int m, n;
scanf("%d%d", &m, &n);
Find_Prime(n);
for(int i = m; i <= n; i++)
printf("%d\n", prime[i-1]);
return 0;
}
六、大整数运算
#include<stdio.h>
#include<string.h>
int convert(char str[], int num[]) //将字母转变为数字,按照低位到高位存放
{
int i, len = strlen(str);
for(i = 0; i < len; i++)
{
num[i] = str[len-i-1] - '0';
}
return len;
}
//大整数加法
void add(char *str1, char *str2)
{
int a[1001] = {0}, b[1001] = {0}; //数组置0
int n1, n2, n;
n1 = convert(str1,a);
n2 = convert(str2,b);
n = n1 >= n2?n1:n2;
int i, flag = 0; //flag为进位
for(i = 0; i < n; i++)
{
int temp = (a[i] + b[i] + flag)/10; //商为进位,余数为当前位结果
a[i] = (a[i] + b[i] + flag)%10;
flag = temp;
}
if(flag) //最高位产生进位
a[n++] = flag;
for(i = n-1; i >= 0; i--)
printf("%d", a[i]);
printf("\n");
}
//大整数减法
void sub(char *str1, char *str2)
{
int a[1001] = {0}, b[1001] = {0}; //数组置0
int n1, n2, n, i, flag = 0; //flag为进位;
char *temp;
if(strlen(str1) < strlen(str2) || (strlen(str1) == strlen(str2) && strcmp(str1, str2) < 0))
{ //判断大小输出负号
temp = str1;
str1 = str2;
str2 = temp;
printf("-");
}
n1 = convert(str1,a);
n2 = convert(str2,b);
n = n1 >= n2?n1:n2;
if(n1 >= n2)
{
n =n1;
}
for(i = 0; i < n; i++)
{
if(a[i] < b[i]) //借位
{
a[i+1]--;
a[i] += 10;
}
a[i] = a[i] - b[i];
}
while(n > 1 && a[n-1] == 0) //去掉高位的0,同时至少保留一位最低位
{
n--;
}
for(i = n-1; i >= 0; i--)
printf("%d", a[i]);
printf("\n");
}
int main()
{
char str1[1001], str2[1001];
while(scanf("%s%s", str1, str2) != EOF)
{
add(str1, str2);
sub(str1, str2);
}
return 0;
}
七、日期差值
- 题目描述:
有两个日期,求两个日期之间的天数,如果两个日期是连续的,则规定他们之间的天数为两天。
每组输出一行,即日期差值
- 输入&输出:
20130101
20130105
5
- 代码:
#include<stdio.h>
int month[13][2] = {{0,0}, {31,31}, {28,29}, {31,31}, {30,30}, {31,31}, {30,30}, {31,31}, {31,31}, {30,30}, {31,31}, {30,30}, {31,31}
};
bool isLeap(int year)
{
return (year%4 == 0 && year%100 != 0 || year%400 == 0);
}
int main()
{
int time1, y1, m1, d1;
int time2, y2, m2, d2;
while(scanf("%d%d", &time1, &time2) != EOF)
{
if(time1 > time2) //第一个日期晚于第二个日期,则交换
{
int temp = time1;
time1 = time2;
time2 = temp;
}
y1 = time1/10000,m1 = time1%10000/100, d1 = time1%100;
y2 = time2/10000,m2 = time2%10000/100, d2 = time2%100;
int ans = 1; //记录结果
while(y1 < y2 || m1 < m2 || d1 < d2)
{
d1++;
if(d1 == month[m1][isLeap(y1)]+1) //当月天数+1正好为下一个月1号
{
m1++; //日期变为下个月1号
d1 = 1;
}
if(m1 == 13) //月份满12月
{
y1++; //日期变为下一年的1月
m1 = 1;
}
ans++;//结果
}
printf("%d\n", ans+1); //这里要注意题目,连续的两天,天数为2
}
return 0;
}
八、牛顿迭代法
牛顿迭代法(Newton’s method)又称为牛顿-拉夫逊(拉弗森)方法(Newton-Raphson method),它是牛顿在17世纪提出的一种在实数域和复数域上近似求解方程的方法。
该方法使用函数的泰勒级数的前面几项来寻找方程 的根。牛顿迭代法是求方程根的重要方法之一,几何上就是不断用(x,f(x))的切线来逼近方程。
/*
x^3 - a = 0
立方根公式:x = (2*x + a/x/x)/3;
x^2 - a = 0
平方根公式:x = (x + a/x)/2
*/
#include<stdio.h>
double my_abs (double x)
{
return x > 0 ? x:-x;
}
double getCube(double y)
{
double x = 1.0;
while(my_abs(x*x*x-y)>1e-7)
{
x = (2*x + y/x/x)/3;
}
return x;
}
int main()
{
double input;
scanf("%lf", &input);
printf("%.1lf\n", getCube(input));
return 0;
}