树,图,查找,排序。数据结构学的差不多了可以尝试写点算法题了。
1.水仙花数
2.韩信点兵
3.倒三角形
4.子序列的和
5.分数化小数
6.排列
7.蛇形填数
8.WERTYU
9.生成元
10.全排列
11.最大公约数
12.杨辉三角
1.水仙花数:输出100~999中的所有水仙花数。若3位数ABC满足ABC=A3+B3+C3,则称其为水仙花数。例如153=13+53+33,所以153是水仙花数。
#include<stdio.h>
int main(){
int a;
int b;
int c;
int t;
for(int i = 100;i<1000;i++){
t = i;
a = t/100;
t = i-a*100;
b = t/10;
c = t-b*10;
if(i==a*a*a+b*b*b+c*c*c){
printf("%d\n",i);
}
}
}
1.韩信点兵:相传韩信才智过人,从不直接清点自己军队的人数,只要让士兵先后以三人一排、五人一排、七人一排地变换队形,而他每次只掠一眼队伍的排尾就知道总人数了。输入包含多组数据,每组数据包含3个非负整数a,b,c,表示每种队形排尾的人数(a<3,b<5,c<7),输出总人数的最小值(或报告无解)。已知总人数不小于10,不超过100。输入到文件结束为止。
样例输入:
2 1 6
2 1 3
样例输出:
Case 1: 41
Case 2: No answer
#include<iostream>
using namespace std;
int main(){
freopen("in.txt","r",stdin);
//freopen("out.txt","w",stdout);
int a;
int b;
int c;
bool flag = false;
while(cin >>a>>b>>c){
int q;
int w;
int e;
flag = false;
for(int i=10;i<=100;i++){
q = i%3;
w = i%5;
e = i%7;
if(q==a && w==b && e==c){
cout<<i<<endl;
flag = true;
break;
}
}
if(!flag){
cout <<"No answer"<<endl;
}
}
fclose(stdin);
//fclose(stdout);
}
3.倒三角形:输入正整数n≤20,输出一个n层的倒三角形。例如,n=5时输出如下:
#########
#######
#####
###
#
#include<iostream>
using namespace std;
void print(int a,int b){
for(int i = 0;i<b;i++){
cout << " ";
}
for(int i = 0;i<a;i++){
cout << "#";
}
}
int main(){
int t;
cin >> t;
int b = 0;
int a = 2*t-1;
while(a>=1){
print(a,b);
cout <<"\n";
b++;
a=a-2;
}
}
4.子序列的和:输入两个正整数n<m<106,输出,保留5位小数。输入包含多组数据,结束标记为n=m=0。
样例输入:
2 4
65536 655360
0 0
样例输出:
Case 1: 0.42361
Case 2: 0.00001
#include<iomanip>
using namespace std;
int main(){
freopen("sbusequence.in.txt","r",stdin);
int a;//用int第二组会溢出,改写表达式
int b;
double s = 0;
int t = 1;
while(cin>>a>>b){
s = 0.0;
if(a==0 && b==0){
return 0;
}
for(int i=a;i<=b;i++){
s = s + 1.0/i/i;
}
cout <<"Case "<<t<<":"<<fixed<<setprecision(5)<<s<<endl;//fixed不使用科学计数法,setprecision设置精度
t++;
}
fclose(stdin);
}
5.分数化小数:输入正整数a,b,c,输出a/b的小数形式,精确到小数点后c位。a,b≤106,c≤100。输入包含多组数据,结束标记为a=b=c=0。
样例输入:
1 6 4
0 0 0
样例输出:
Case 1: 0.1667
#include<iostream>
#include<iomanip>
using namespace std;
int main(){
freopen("decimal.in.txt","r",stdin);
int a;
int b;
int c;
int t;
double s;
int q=1;
while(cin>>a>>b>>c){
if(a==0 && b==0 && c==0){
return 0;
}
s = a/(b+0.0);//转换为浮点数
cout <<"Case "<<q<<":"<<fixed<<setprecision(c)<<s<<"\n";
q++;
}
fclose(stdin);
}
6.排列:用1,2,3,…,9组成3个三位数abc,def和ghi,每个数字恰好使用一次,要
求abc:def:ghi=1:2:3。按照“abc def ghi”的格式输出所有解,每行一个解。
#include<iostream>
#include<iomanip>
using namespace std;
int a;
int b;
int c;
int q,w,e,r,t,y,u,i,o;
int s[] = {0,0,0,0,0,0,0,0,0,0};
int z;
bool fit(int num){
a = num/1000000;
b = num/1000%1000;
c = num%1000;
if(b == 2*a && c == 3*a){
return true;
}else{
return false;
}
}
int get(){
return 0+
+s[1]*100000000
+s[2]*10000000
+s[3]*1000000
+s[4]*100000
+s[5]*10000
+s[6]*1000
+s[7]*100
+s[8]*10
+s[9]*1;
}
int main(){
for(int q=1;q<=9;q++){
s[q] = 1;
for(int w=1;w<=9;w++){
if(s[w] == 0){
s[w] = 2;
for(int e=1;e<=9;e++){
if(s[e] == 0){
s[e] = 3;
for(int r=1;r<=9;r++){
if(s[r] == 0){
s[r] = 4;
for(int t=1;t<=9;t++){
if(s[t] == 0){
s[t] = 5;
for(int y=1;y<=9;y++){
if(s[y] == 0){
s[y] = 6;
for(int u=1;u<=9;u++){
if(s[u] == 0){
s[u] = 7;
for(int i=1;i<=9;i++){
if(s[i] == 0){
s[i] = 8;
for(int o=1;o<=9;o++){
if(s[o] == 0){
s[o] = 9;
z = get();
if(fit(z)) cout <<z<<"\n";
s[o] = 0;
}
}
s[i] = 0;
}
}
s[u] = 0;
}
}
s[y] = 0;
}
}
s[t] = 0;
}
}
s[r] = 0;
}
}
s[e] = 0;
}
}
s[w] = 0;
}
}
s[q] = 0;
}
}
虽然丑了点吧,但还是放出来当个纪念吧。。
7:蛇形填数。在n×n方阵里填入1,2,…,n×n,要求填成蛇形。例如,n=4时方阵为:
10 11 12 1
9 16 13 2
8 15 14 3
7 6 5 4
#include<iostream>
#include<iomanip>
using namespace std;
enum Direction{
Left,
Right,
Up,
Down,
};
int main(){
int a;
cout <<"蛇形填数,阶数:";
cin>>a;
int num = a*a;
int i = 1;
int snake[a+1][a+1];
for(int q=1;q<=a;q++){
for(int w=1;w<=a;w++){
snake[q][w] = 0;
}
}
int hang = 1;
int lie = a;
Direction dir = Down;
for(i=1;i<=num;i++){
snake[hang][lie] = i;
if(dir==Down){
if(snake[hang+1][lie] == 0 && hang<a){
hang++;
continue;
}else{
if(snake[hang][lie-1] == 0 && lie>1){
lie--;
dir = Left;
continue;
}else{
break;
}
}
}
if(dir==Left){
if(snake[hang][lie-1] == 0 && lie>1){
lie--;
continue;
}else{
if(snake[hang-1][lie] == 0 && hang>1){
hang--;
dir = Up;
continue;
}else{
break;
}
}
}
if(dir==Up){
if(snake[hang-1][lie] == 0 && hang>1){
hang--;
continue;
}else{
if(snake[hang][lie+1] == 0 && lie<a){
lie++;
dir = Right;
continue;
}else{
break;
}
}
}
if(dir==Right){
if(snake[hang][lie+1] == 0 && dir<a){
lie++;
continue;
}else{
if(snake[hang+1][lie] == 0 && hang<a){
hang++;
dir = Down;
continue;
}else{
break;
}
}
}
}
for(int q=1;q<=a;q++){
for(int w=1;w<=a;w++){
cout <<snake[q][w]<<" ";
}
cout <<"\n";
}
}
虽说我并没有考虑优化,但是刘大爷写成这样我也是服气的。
while(count<n*n){
while(x+1<n && !a[x+1][y]) a[++x][y]=++count;//右下
while(y-1>=0 &&!a[x][y-1]) a[x][--y]=++count;//向左
while(x-1>=0 &&!a[x-1][y]) a[--x][y]=++count;//左上
while(y+1<n &&!a[x][y+1]) a[x][++y]=++count;//向右
}
8 WERTYU:把手放在键盘上时,稍不注意就会往右错一位。这样,输入Q会变成输入W,输入J会变成输入K等。输入一个错位后敲出的字符串(所有字母均大写),输出打字员本来想打出的句子。输入保证合法,即一定是错位之后的字符串。例如输入中不会出现大写字母A。
样例输入:
O S, GOMR YPFSU/
样例输出:
I AM FINE TODAY.
#include<iostream>
#include<iomanip>
using namespace std;
int main(){
freopen("UVa10082.in.txt","r",stdin);
char s[] = "`1234567890-=QWERTYUIOP[]\\ASDFGHJKL;'ZXCVBNM,./";//char数组就是字符串
char a ;
bool flag = false;
while(true){
a = cin.get();
if(a != EOF){
for(int i=0;i <47;i++){
if(s[i] == a){
cout <<s[i-1];
flag = true;
}
}
if(flag){
flag=false;
continue;
}
cout <<a;
}else{
break;
}
}
fclose(stdin);
}
把可能性写出来再查表的思想非常好。下面一题就是这种思想的应用。
9 生成元:如果x加上x的各个数字之和得到y,就说x是y的生成元。给出n(1≤n≤100000),求最小生成元。无解输出0。例如,n=216,121,2005时的解分别为198,0,1979。
#include<iostream>
#include<iomanip>
using namespace std;
int main(){
int s[100001];
int a,b,c,d,e;
int t;
int num;
for(int i=0;i<100001;i++){
s[i] = 0;
}
for(int i=1;i<100000;i++){
a = i/10000;
b = i/1000%10;
c = i/100%10;
d = i/10%10;
e = i%10;
t = i+a+b+c+d+e;
if(s[t] == 0){
s[t] = i;
}
}
while(true){
cin >>num;
if(num==0) break;
cout<<"最小生成元:" <<s[num]<<"\n";
}
return 0;
}
10:全排列:生成全排列
#include<iostream>
#include<iomanip>
using namespace std;
void print(int s[],int n){
for(int i=1;i<=n;i++){
cout << s[i];
}
cout <<"\n";
}
void per(int a,int n,int s[]){
if(a>n){
print(s,n);
}else{
for(int i=1;i<=n;i++){
if(s[i] == 0){
s[i] = a;
per(a+1,n,s);
s[i] = 0;
}
}
}
}
int main(){
int n;
cin >> n;
int s[n+1];
for(int i=0;i<=n;i++){
s[i] = 0;
}
per(1,n,s);
}
下面这个是改进后的版本,生成的数字有序
#include<iostream>
#include<iomanip>
using namespace std;
//通过辅助数组c查看哪个数还没有填 。对于可重集,只要c的数小于重复数,即可填写
//1.参数准备
//2.调用递归
//3.边界检测和处理
//4.递归处理和调用
//明显看出递归的效率不行,7的时候性能就不行了
void print(int s[],int n){
for(int i=1;i<=n;i++){
cout << s[i];
}
cout <<"\n";
}
void per(int a,int n,int s[],int c[]){
if(a>n){
print(s,n);
}else{
for(int i=1;i<=n;i++){
if(c[i] == 0){
c[i] = 1;
s[a] = i;
per(a+1,n,s,c);
c[i] = 0;
}
}
}
}
int main(){
int n;
cin >> n;
int s[n+1];
int c[n+1];
for(int i=0;i<=n;i++){
s[i] = 0;
c[i] = 0;
}
per(1,n,s,c);
}
11 最大公约数:
#include<iomanip>
using namespace std;
int main(){
int a,b;
cout<<"辗转相除法求最大公约数:\n";
cout<<"a=";
cin>>a;
cout<<"b=";
cin>>b;
int c;
if(a<=b){
c=a;
a=b;
b=c;
}
while(b != 0){
c = a%b;
a=b;
b=c;
}
cout<<"最大公约数:"<<a;
}
以及递归版本:
int gcd(int a,int b){
return b==0?a:gcd(b,a%b);
}
12杨辉三角
杨辉三角用于生成二项式的系数
#include<iostream>
#include<iomanip>
using namespace std;
int main(){
int a;
cin >> a;
int s[a+1][a+1];
for(int i=0;i<=a;i++){
for(int j=0;j<=a;j++){
s[i][j] = 0;
}
}
//输入对应次幂的杨辉三角
s[0][0] = 1;
s[1][0] = 1;
s[1][1] = 1;
for(int i=2;i<=a;i++){
s[i][0]=1;
for(int j=1;j<=a;j++){
s[i][j] = s[i-1][j-1] + s[i-1][j];
}
}
for(int i=0;i<=a;i++){
for(int j=0;j<=a;j++){
if(s[i][j] !=0) cout <<" "<< s[i][j];
}
cout << "\n";
}
}