郭继展,郭勇,苏辉《程序算法与技巧精选》,机械工业出版社,2008年5月第一版,ISBN 978-7-111-23816-4,第7.3节:求自幂数——用数组预作乘法提高速度100倍。
(1)想用自己的语言总结书上的内容;
(2)用自己的笔记本电脑测试下各个方法间,效率差距究竟有多大;
(3)用自己的风格写一遍代码,加深对知识的理解,也方便以后自己复习。
我会先在第二章讨论各种算法的效率问题,并贴所有源代码供读者验证,也对结果进行截图方便不愿跑代码的懒读者快速读完本篇文章。在第三章写一段计算所有自幂数的小程序。
PS:本来排版很好的,涉及到英文的书写时,博客给我自动换行换到难看死了……
#include <iostream> #include <cmath> #include <ctime> using namespace std; clock_t start__; #define tic start__=clock() #define toc cout<<(clock()-start__)*1000/CLOCKS_PER_SEC<<"ms\n" void zms1(int x) // 自幂数拼音首字母:zms,后缀+数字用于区别不同算法的zms函数 { int l=pow(10,x-1),r=pow(10,x),i,i0,j,t,a; for(i=l; i<r; i++) { i0 = i; // 拷贝i的一个副本 for(t=j=0;j<x;j++) { a = i0%10; // 得到最末位的值 t += a*pow(10,j)-pow(a,x); i0 /= 10; } if(t==0) cout<<i<<endl; } } int main() { tic,zms1(7),toc; return 0; }
#include <iostream> #include <cmath> #include <ctime> using namespace std; clock_t start__; #define tic start__=clock() #define toc cout<<(clock()-start__)*1000/CLOCKS_PER_SEC<<"ms\n" void zms2() { int i,j,k,l,m,n,o; //用来穷举各个位的值的变量,即值本身为ijklmno for(i=1;i<10;i++) for(j=0;j<10;j++) for(k=0;k<10;k++) for(l=0;l<10;l++) for(m=0;m<10;m++) for(n=0;n<10;n++) for(o=0;o<10;o++) { if(pow(i,7)+pow(j,7)+pow(k,7)+pow(l,7)+pow(m,7)+pow(n,7)+pow(o,7) ==1000000*i+100000*j+10000*k+1000*l+100*m+10*n+o) cout<<i<<j<<k<<l<<m<<n<<o<<endl; } } int main() { tic,zms2(),toc; return 0; }
#include <iostream> #include <cmath> #include <ctime> using namespace std; clock_t start__; #define tic start__=clock() #define toc cout<<(clock()-start__)*1000/CLOCKS_PER_SEC<<"ms\n" void zms3() { int i,j,k,l,m,n,o; int a[7][10]; // 存储中间计算量 for(i=0;i<7;i++) for(j=0;j<10;j++) a[i][j] = j*pow(10,6-i) - pow(j,7); // 推导出公式后赋值 for(i=1;i<10;i++) for(j=0;j<10;j++) for(k=0;k<10;k++) for(l=0;l<10;l++) for(m=0;m<10;m++) for(n=0;n<10;n++) for(o=0;o<10;o++) { if(a[0][i]+a[1][j]+a[2][k]+a[3][l]+a[4][m]+a[5][n]+a[6][o]==0) cout<<i<<j<<k<<l<<m<<n<<o<<endl; } } int main() { tic,zms3(),toc; return 0; }
#include <iostream> #include <cmath> #include <ctime> using namespace std; clock_t start__; #define tic start__=clock() #define toc cout<<(clock()-start__)*1000/CLOCKS_PER_SEC<<"ms\n" void zms4() { int i,j,k,l,m,n,o,p,q; int a[9][10]; // 存储中间计算量 for(i=0;i<9;i++) for(j=0;j<10;j++) a[i][j] = j*pow(10,8-i) - pow(j,9); // 推导出公式后赋值 for(i=1;i<10;i++) for(j=0;j<10;j++) for(k=0;k<10;k++) for(l=0;l<10;l++) for(m=0;m<10;m++) for(n=0;n<10;n++) for(o=0;o<10;o++) for(p=0;p<10;p++) for(q=0;q<10;q++) { if(a[0][i]+a[1][j]+a[2][k]+a[3][l]+a[4][m]+a[5][n]+a[6][o]+a[7][p]+a[8][q]==0) cout<<i<<j<<k<<l<<m<<n<<o<<p<<q<<endl; } } int main() { tic,zms4(),toc; return 0; }
#include <iostream> #include <cmath> #include <ctime> using namespace std; clock_t start__; #define tic start__=clock() #define toc cout<<(clock()-start__)*1000/CLOCKS_PER_SEC<<"ms\n" void zms5() { int x = 9,c=0; // x代表是几位自幂数,c用于统计解的个数 int i,j,k,l,m,n,o,p,q; int t,a[9][10]; // 存储中间计算量 for(i=0;i<x;i++) for(j=0;j<10;j++) // 这里,我们将矩阵赋值公式再进一步一般化处理 a[i][j] = j*pow(10,x-i-1) - pow(j,x); // 推广到x位自幂数的赋值 for(i=1;i<10;i++) { t = a[0][i]; for(j=0;j<10;j++) { t += a[1][j]; for(k=0;k<10;k++) { t += a[2][k]; for(l=0;l<10;l++) { t += a[3][l]; for(m=0;m<10;m++) { t += a[4][m]; for(n=0;n<10;n++) { t += a[5][n]; for(o=0;o<10;o++) { t += a[6][o]; for(p=0;p<10;p++) { t += a[7][p]; for(q=0;q<10;q++) { t += a[8][q]; if(!t) printf("%2d: ",++c),cout<<i<<j<<k<<l<<m<<n<<o<<p<<q<<endl; t -= a[8][q]; } t -= a[7][p]; } t -= a[6][o]; } t -= a[5][n]; } t -= a[4][m]; } t -= a[3][l]; } t -= a[2][k]; } t -= a[1][j]; }} } int main() { tic,zms5(),toc; return 0; }
#include <iostream> #include <cmath> #include <ctime> using namespace std; clock_t start__; #define tic start__=clock() #define toc cout<<(clock()-start__)*1000/CLOCKS_PER_SEC<<"ms\n" void zms6() { int x = 9,c=0; // x代表是几位自幂数,c用于统计解的个数 int i,j,k,l,m,n,o,p,q; int t,a[9][10]; // 存储中间计算量 for(i=0;i<x;i++) for(j=0;j<10;j++) // 这里,我们将矩阵赋值公式再进一步一般化处理 a[i][j] = j*pow(10,x-i-1) - pow(j,x); // 推广到x位自幂数的赋值 for(i=1;i<10;i++) { t = a[0][i]; for(j=0;j<10;j++) { t += a[1][j]; for(k=0;k<10;k++) { t += a[2][k]; for(l=0;l<10;l++) { t += a[3][l]; for(m=0;m<10;m++) { t += a[4][m]; for(n=0;n<10;n++) { t += a[5][n]; for(o=0;o<10;o++) { t += a[6][o]; for(p=0;p<10;p++) { t += a[7][p]; if(t<0) {t-=a[7][p];continue;} for(q=0;q<10;q++) { t += a[8][q]; if(!t) printf("%2d: ",++c),cout<<i<<j<<k<<l<<m<<n<<o<<p<<q<<endl; t -= a[8][q]; } t -= a[7][p]; } t -= a[6][o]; } t -= a[5][n]; } t -= a[4][m]; } t -= a[3][l]; } t -= a[2][k]; } t -= a[1][j]; }} } int main() { tic,zms6(),toc; return 0; }
#include <iostream> #include <cmath> #include <ctime> using namespace std; clock_t start__; #define tic start__=clock() #define toc cout<<(clock()-start__)*1000/CLOCKS_PER_SEC<<"ms\n" void zms7() { int x = 9,c=0; // x代表是几位自幂数,c用于统计解的个数 int i,j,k,l,m,n,o,p,q; __int64 t,a[9][10]; // 存储中间计算量 for(i=0;i<x;i++) for(j=0;j<10;j++) // 这里,我们将矩阵赋值公式再进一步一般化处理 a[i][j] = j*pow(10,x-i-1) - pow(j,x); // 推广到x位自幂数的赋值 for(i=1;i<10;i++) { t = a[0][i]; for(j=0;j<10;j++) { t += a[1][j]; for(k=0;k<10;k++) { t += a[2][k]; for(l=0;l<10;l++) { t += a[3][l]; for(m=0;m<10;m++) { t += a[4][m]; for(n=0;n<10;n++) { t += a[5][n]; for(o=0;o<10;o++) { t += a[6][o]; for(p=0;p<10;p++) { t += a[7][p]; if(t<0) {t-=a[7][p];continue;} for(q=0;q<10;q++) { t += a[8][q]; if(!t) printf("%2d: ",++c),cout<<i<<j<<k<<l<<m<<n<<o<<p<<q<<endl; t -= a[8][q]; } t -= a[7][p]; } t -= a[6][o]; } t -= a[5][n]; } t -= a[4][m]; } t -= a[3][l]; } t -= a[2][k]; } t -= a[1][j]; }} } int main() { tic,zms7(),toc; return 0; }
#include <iostream> #include <cmath> #include <ctime> using namespace std; clock_t start__; #define tic start__=clock() #define toc cout<<(clock()-start__)*1000/CLOCKS_PER_SEC<<"ms\n" int main() { void zms(int); int x; while(cout<<"请输入要计算几位自幂数:",cin>>x) { if(x<1||x>10) { cout << "输入非法,请重输\n"; continue; } zms(x); cout << endl; } return 0; } void zms(int x) {// 输入参数值只能为[1,10]的整数 int c = 0; // 统计解的个数 int i,j,k,l,m,n,o,p,q,r;// 各个位的数字枚举变量 __int64 t,a[10][10]; //10位自幂数需要用int64,与int差别是9位自幂数计算5秒变8秒 tic; switch(x) { case 1: cout << "一位自幂数(独身数):" << endl; break; case 2: cout << "二位自幂数(无):" << endl; break; case 3: cout << "三位自幂数(水仙花数):" << endl; break; case 4: cout << "四位自幂数(四叶玫瑰数):" << endl; break; case 5: cout << "五位自幂数(五角星数):" << endl; break; case 6: cout << "六位自幂数(六合数):" << endl; break; case 7: cout << "七位自幂数(北斗七星数):" << endl; break; case 8: cout << "八位自幂数(八仙数):" << endl; break; case 9: cout << "九位自幂数(九九重阳数):" << endl; break; case 10: cout << "十位自幂数(十全十美数):" << endl; break; } for(i=0;i<x;i++) for(j=0;j<10;j++) a[i][j] = j*pow(10,x-i-1) - pow(j,x); switch(x) { case 1: printf("%2d: 0\n",++c); for(i=1;i<10;i++) { t = a[0][i]; if(!t) printf("%2d: ",++c),cout<<i<<endl; } break; case 2: for(i=1;i<10;i++) { t = a[0][i]; for(j=0;j<10;j++) { t += a[1][j]; if(!t) printf("%2d: ",++c),cout<<i<<j<<endl; t -= a[1][j]; }} break; case 3: for(i=1;i<10;i++) { t = a[0][i]; for(j=0;j<10;j++) { t += a[1][j]; // if(t<0){t-=a[1][j];continue;} for(k=0;k<10;k++) { t += a[2][k]; if(!t) printf("%2d: ",++c),cout<<i<<j<<k<<endl; t -= a[2][k]; } t -= a[1][j]; }} break; case 4: for(i=1;i<10;i++) { t = a[0][i]; for(j=0;j<10;j++) { t += a[1][j]; for(k=0;k<10;k++) { t += a[2][k]; if(t<0){t-=a[2][k];continue;} for(l=0;l<10;l++) { t += a[3][l]; if(!t) printf("%2d: ",++c),cout<<i<<j<<k<<l<<endl; t -= a[3][l]; } t -= a[2][k]; } t -= a[1][j]; }} break; case 5: for(i=1;i<10;i++) { t = a[0][i]; for(j=0;j<10;j++) { t += a[1][j]; for(k=0;k<10;k++) { t += a[2][k]; for(l=0;l<10;l++) { t += a[3][l]; if(t<0){t-=a[3][l];continue;} for(m=0;m<10;m++) { t += a[4][m]; if(!t) printf("%2d: ",++c),cout<<i<<j<<k<<l<<m<<endl; t -= a[4][m]; } t -= a[3][l]; } t -= a[2][k]; } t -= a[1][j]; }} break; case 6: for(i=1;i<10;i++) { t = a[0][i]; for(j=0;j<10;j++) { t += a[1][j]; for(k=0;k<10;k++) { t += a[2][k]; for(l=0;l<10;l++) { t += a[3][l]; for(m=0;m<10;m++) { t += a[4][m]; if(t<0){t-=a[4][m];continue;} for(n=0;n<10;n++) { t += a[5][n]; if(!t) printf("%2d: ",++c),cout<<i<<j<<k<<l<<m<<n<<endl; t -= a[5][n]; } t -= a[4][m]; } t -= a[3][l]; } t -= a[2][k]; } t -= a[1][j]; }} break; case 7: for(i=1;i<10;i++) { t = a[0][i]; for(j=0;j<10;j++) { t += a[1][j]; for(k=0;k<10;k++) { t += a[2][k]; for(l=0;l<10;l++) { t += a[3][l]; for(m=0;m<10;m++) { t += a[4][m]; for(n=0;n<10;n++) { t += a[5][n]; if(t<0){t-=a[5][n];continue;} for(o=0;o<10;o++) { t += a[6][o]; if(!t) printf("%2d: ",++c),cout<<i<<j<<k<<l<<m<<n<<o<<endl; t -= a[6][o]; } t -= a[5][n]; } t -= a[4][m]; } t -= a[3][l]; } t -= a[2][k]; } t -= a[1][j]; }} break; case 8: for(i=1;i<10;i++) { t = a[0][i]; for(j=0;j<10;j++) { t += a[1][j]; for(k=0;k<10;k++) { t += a[2][k]; for(l=0;l<10;l++) { t += a[3][l]; for(m=0;m<10;m++) { t += a[4][m]; for(n=0;n<10;n++) { t += a[5][n]; for(o=0;o<10;o++) { t += a[6][o]; if(t<0){t-=a[6][o];continue;} // 这里加if,800ms+变500ms+ for(p=0;p<10;p++) { t += a[7][p]; if(!t) printf("%2d: ",++c),cout<<i<<j<<k<<l<<m<<n<<o<<p<<endl; t -= a[7][p]; } t -= a[6][o]; } t -= a[5][n]; } t -= a[4][m]; } t -= a[3][l]; } t -= a[2][k]; } t -= a[1][j]; }} break; case 9: for(i=1;i<10;i++) { t = a[0][i]; for(j=0;j<10;j++) { t += a[1][j]; for(k=0;k<10;k++) { t += a[2][k]; for(l=0;l<10;l++) { t += a[3][l]; for(m=0;m<10;m++) { t += a[4][m]; for(n=0;n<10;n++) { t += a[5][n]; for(o=0;o<10;o++) { t += a[6][o]; for(p=0;p<10;p++) { t += a[7][p]; if(t<0){t-=a[7][p];continue;} // 这里加if,8秒变5秒 for(q=0;q<10;q++) { t += a[8][q]; if(!t) printf("%2d: ",++c),cout<<i<<j<<k<<l<<m<<n<<o<<p<<q<<endl; t -= a[8][q]; } t -= a[7][p]; } t -= a[6][o]; } t -= a[5][n]; } t -= a[4][m]; } t -= a[3][l]; } t -= a[2][k]; } t -= a[1][j]; }} break; case 10: for(i=4;i<5;i++) { t = a[0][i]; for(j=0;j<10;j++) { t += a[1][j]; for(k=0;k<10;k++) { t += a[2][k]; for(l=0;l<10;l++) { t += a[3][l]; for(m=0;m<10;m++) { t += a[4][m]; for(n=0;n<10;n++) { t += a[5][n]; for(o=0;o<10;o++) { t += a[6][o]; for(p=0;p<10;p++) { t += a[7][p]; for(q=0;q<10;q++) { t += a[8][q]; if(t<0){t-=a[8][q];continue;} // 我擦,这里加个负值判断,80秒变成6秒! for(r=0;r<10;r++) { t += a[9][r]; if(!t) printf("%2d: ",++c),cout<<i<<j<<k<<l<<m<<n<<o<<p<<q<<r<<endl; t -= a[9][r]; } t -= a[8][q]; } t -= a[7][p]; } t -= a[6][o]; } t -= a[5][n]; } t -= a[4][m]; } t -= a[3][l]; } t -= a[2][k]; } t -= a[1][j]; }} break; } cout<<"求解完毕!共用时"; toc; }