C语言名题精选百则——数字问题
C语言名题精选百则——数字问题
尊重他人的劳动,支持原创
这篇博文,D.S.Qiu将对《C语言名题精选百则》第二章进行整理推出,本章一共16个问题,不光只是书上的名题,还会依据互联网的资源进行不断补充,加强(由于匆忙,暂时还只是罗列的过程,不过很快就有深度的发掘)。如果你有建议、批评或补充,请你不吝提出(email:gd.s.qiu@gmail.com,或者直接在本文末评论)。你的支持和鼓励,我将渐行渐远!
这篇博文整理的太艰难了,其中一度想放弃,个人觉得难度有点大,如果没有需求驱动的话,很难读下去,但最终为了保持文章的完整性,还是硬着头皮去截图整理。这16个问题主要经常的是对质数的求解,因式分解,整数自乘(快速求解),Fibonacci数(快速求解),二项式求解(快速求解),阶乘(快速求解),这些都是数论或者组合数学的基本内容,但要通过计算机基本求解的算法赴复杂度过高,文中给出了相应的快速算法,对有需求的读者来说,还是可以喜出望外的(也只是大概的理解了下),应该还有更多精彩的求解方法(日后定当补充)。终于写完了,没有你的支持和鼓励,很难继续下去,下一篇是《排列,组合与集合》。
问题2.1 Armstrong 数(ARMS1.C,ARMS2.C )
在三位的正整数中,例如abc,有一些可以满足a³+b³+c³ = abc的条件,也就是说, 各个位数的立方和正好是该数的本身,这些数称为Armstrong数。试编写一个程序来求出
所有的三位Armstrong数。
【说明】
这是个常见的问题,许多课本、习题集都有。解决的基本方法就在于有没有办法从一 个三位数中把它的3个位数取出(例如,把379分解成3、7与9),或者在已知3个位数 时把该三位数算出来(例如,已知百位为5,十位为1,个位为9,则三位数为519)。
另一个变形是给出一个数,证明它是否为一个Armstromg数。这两者类似,由自己产 生的数可以永远控制在三位,但是后者却一定要去测试它是不是三位数。
如何测试一个数是否为三位数呢?有的书中介绍这样一种方法(见程序UGLY.C), 使用对数log()以及指数exp()函数,不仅如此,还要用四舍五入(在C语言中只好加上 0.5再转型成整数)。为什么?原来只是在取出输入数据的某一个位数而已。一个简单的 程序写得如此复杂,大多数初学者恐怕都很难看明白。在此给出一个提示,千万不要重蹈覆辙。
(1)如果要确认x是个五位数,就看x/100000是否为零。如果为零,那么x的位数 不会超过五位。接着再检查x是否真的是五位,这就要看:
(x % 100000)/10000
是否为零,如果不为零,这个值就是x中从右向左数第五位数的值;如果是零,x就最多只能有四位而已。为什么?因为x%100000是把x用100000去除的余数,值在0〜99999 之间,正是x的右边五位,再用10000去除,那就是第五位的值了;如果x是五位数,那么这个位数就一定大于1,如程序2-1所示。
【程序】
程序2-1(UGLY.C)
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <math.h>void main(void) {int number; /* the input number */int pos, ten_pow; /* # of digits and 10^x */int arm_no; /* computed Armstrong Number*/int temp, i; /* working variables */float expon; /* computed exponent */char line[100]; /* input buffer */printf("\nPlease key in number : "); /* get a number*/gets(line);number = atoi(line);pos = 0; /* count # of digits */ten_pow = 1; /* power of 10, 10^0=1 */do { /* start counting */ten_pow *= 10; /* one more digit... */pos++;} while (ten_pow < number);if (ten_pow == number) /* all 10^x are not Arm # */printf("\n%d is not an Armstrong Number.", number);else { /* not 10^x */ten_pow = number; /* now ten_pow is a temp var*/arm_no = 0; /* initial value for Arm. # */for (i = pos-1; i >= 1; i--) { /* scan from R->L*/expon = exp(i*log(10.0)); /* the ugly part */temp = ten_pow / expon; /* you do it... */ten_pow %= (int)(expon + 0.5);arm_no += exp(pos*log(temp)) + 0.5;}arm_no += exp(pos*log(ten_pow)) + 0.5;if (arm_no == number)printf("\n%d is an Armstrong Number.", number);elseprintf("\n%d is not an Armstrong Number.", number);} }
(2)如果这两个条件都正确,则x是一个五位数。
(3)按照这个技巧,要找出x的第三位(自右往左算),那就是
(x%1000)/100
(4)用下面的式子也可以求出x的第三位的值:
(x/100)%10
问题实现
/* ------------------------------------------------------ */ /* PROGRAM Armstrong Number Search : */ /* This program searches all 3-digit Armstrong Numbers */ /* and thus numbers in the range of 0-99 are not counted. */ /* */ /* Copyright Ching-Kuang Shene June/29/1989 */ /* ------------------------------------------------------ */#include <stdio.h>void main(void) {int p, q, r; /* three digits */int p_cube, q_cube, r_cube; /* their cubes */int p100, q10; /* their position values */int number; /* the computed number */int cube_sum; /* the sum of the cubes */int count = 0; /* counter */printf("\nArmstrong Number Search");printf("\n=======================");printf("\n\nCount Number");printf( "\n----- ------");for (p = 1, p100 = 100; p <= 9; p++, p100+=100) {p_cube = p*p*p;for (q = q10 = 0; q <= 9; q++, q10+=10) {q_cube = q*q*q;for (r = 0; r <= 9; r++) {r_cube = r*r*r;number = p100 + q10 + r;cube_sum = p_cube + q_cube + r_cube;if (number == cube_sum) printf("\n%3d%9d", ++count, number);}}}printf("\n\nThere are %d 3-digit Armstrong Numbers.", count); }
问题2.2数字谜(TRENTE.C )
在一些游戏与休闲的书刊中,经常会看到如下的数字谜
试编写一个程序进行破解(看下面的规则说明)。
【说明】
数字谜的规则是这样的:
(1)不同的英文字母表示不同的数字。因此,题目中最右边一行的T、Q、E就是不同的数。
(2)每一个数最左边一位不是0。所以上面的谜题中,V、C、T都不是0。
(3)上面的题目是加,那就表示VINGT这个五位数与CINQ这个四位数的两倍相加 后,会得到TRENTE这个六位数,并且数字的安排如谜语所示。
在解这些数字谜时,很多人都会不知不觉地用最笨拙的方法,因此可能执行好几分钟, 甚至好几小时都得不到结果。就以上题为例,它一共有9个不同的字母,因此耗用10个数 字符号中的9个,很多人就会写出下面的形式,如程序2-2所示。
【程序】
程序2-2
for(v=1;v<=9;v++)
for(I=0;I<=9;I++)
……
for(E=0;E<=9;E++)
{
VINGT=……;
CINQ=……;
TRENTE=……;
if(TRENTE == VINGT + CINQ +CINQ)
{
……
}
}
如果用这个程序,那么也许一两个小时也不一定能够算出结果,因为在最内层循环中 的if 一共要执行将近10^9,近一亿次,所以这是最笨的方法。通常,用一点小学算术知识就可以节省大量的计算时间。换言之,可以用四则运算来 找出某个字母值的范围(如偶数、奇数、5〜9、3或4等,而不是0〜9),范围越小,程序的工作就越少,执行起来就越快。
不妨从这一点出发,就本题而给出一些提示:
(1)因为3个位数相加,最大就是9+9+9=27,如果从这一个位数的右边一位会有进 位,那么这个进位就最多是2,所以3个位数再加上进位的最大值是29,所以该位数和是 9,而进位是2。
(2)现在看V那位,加上进位之后得到TR,因为V最大是9,进位最大是2,所以 TR的最大值是11。因为T是结果的第一位,所以不能是0,因此只好是1;但结果前两位 是TR, TR最大是11,现在T是1,于是R只能是0。注意,如果R是2〜9中任意一个, 那就表示没有从R到T的进位,因而T就是0 了。所以从一点看来,两个值就固定了,即T=1, R=0。
(3)再来看V,V—定大于8。为什么?千位数的进位最大是2,要一个数加上2而 有两位数,那么这个数不就至少是8吗?
(4)看个位数的E。它是由T加上两个Q得来的,已知T是1,而2Q—定是偶数, 所以E是个奇数。
就用这4点提示,T与R的循环就不必了; E的循环有3、5、7、9 (注意,T是1, E 就不能用1); V的循环只能用8与9。还没有决定的就剩下I、N、G、C与Q5个,所以循 环就有7层,I、N、G与Q为0〜9; C为2〜9 (因为C是第一位,不能是0,也不能是1, 因为T是1),E是3、5、7、9; V是8与9,所以最内层的if就执行了 10^4x7x4x2次而已,于是用这个方法写成的程序所花的时间大约是前面所提到的:
10^4x7x4x2/10^9=0.056%
因此可以看到节省了多少时间。
思考一下,另外是否还有其他可以节省时间的方法呢?
问题实现
/* ------------------------------------------------------ */ /* PROGRAM Number Puzzle : */ /* This is first solution of the number puzzle. It is */ /* written under the guidelines in my book. For each */ /* digit, there corresponds a for loop and an if statement*/ /* to prevent duplicated digits. Read it carefully. */ /* */ /* Copyright Ching-Kuang Shene June/30/1989 */ /* ------------------------------------------------------ */#include <stdio.h>void main(void) {long I, N, R=0, E, V, G, C, Q, T=1;long IN, VINGT, CINQ, TRENTE;long sum;printf("\nNumber Puzzle\n");printf("\n VINGT");printf("\n CINQ");printf("\n+) CINQ");printf("\n--------");printf("\n TRENTE\n");for (V=8; V<=9; V++)for (I=0; I<=9; I++)if (I != V && I!=T)for (N=0; N<=9; N++)if (N!=I && N!=V && N!=T) {IN = I*10 + N;for (G=0; G<=9; G++)if (G!=N && G!=I && G!=V && G!=T && G!=R) for (C=2; C<=9; C++)if (C!=G && C!=N && C!=I && C!= V && C!=T && C!=R)for (Q=2; Q<=9; Q++)if (Q!=C && Q!=G && Q!=N && Q!=I && Q!=V && Q!=T && Q!=R)for (E=3; E<=9; E+=2)if (E!=Q && E!=C && E!=G && E!=N && E!=I&& E!=V && E!=T && E!=R) {TRENTE=((((T*10+R)*10+E)*10+N)*10+T)*10+E;VINGT=((V*100+IN)*10+G)*10+T;CINQ =(C*100+IN)*10+Q;sum=VINGT+CINQ+CINQ;if (sum==TRENTE) {printf("\n\nThe answer is :\n");printf("\n%8ld", VINGT);printf("\n%8ld", CINQ);printf("\n+)%6ld", CINQ);printf("\n--------");printf("\n%8ld", TRENTE);}}} }
问题2.3求质数(PRIME1.C )
试编写一个程序,找出前N (如200)个质数。如果没有进一步要求,这不是难题。 但在此希望从所知的、使用除法的方法中,用最快的办法来编写程序。
【说明】
可能最先想到的办法,就是让某个变量i从2变到N,然后检查它是不是质数,如果是就显示出来,如果不是,就检查下一个。这是正确的做法,但却没有注意到一个小细节, 因而使程序运行速度变慢。当然,2是质数,但所有2的倍数都不是质数,如果令i从2 变到N,不就很冤枉地测试了 4,6,8,10,…这些数?所以第一点提示是测试2,3,5,7,…,N,即 2与所有奇数就足够了。同理,3是质数,但6,9,12,…这些3的倍数却不是,因此,如果能够把2与3的倍数都跳过去而不测试,任意连续的6个数中,就只会测试两个而已。以6n,6n+1,6n+2,6n+3,6n+4,6n+5 为例,6n,6n+2,6n+4 是偶数,又 6n+3 是 3 的倍数,所以如果 把2与3的倍数都不理会,要测试的数就只留下6n+1与6n+5而已,因而工作量只是前述想法的2/6=1/3,应该用这个方法去编写程序。
/* ------------------------------------------------------ */ /* PROGRAM prime number generator : */ /* This program generates first MAXSIZE-1 primes by */ /* using the conventional division method, but multiples */ /* of 2 and 3 are not tested. Therefore it is faster. */ /* */ /* Copyright Ching-Kuang Shene July/02/1989 */ /* ------------------------------------------------------ */#include <stdio.h>#define MAXSIZE 100 #define YES 1 #define NO 0void main(void) {int prime[MAXSIZE]; /* array to contains primes */int gap = 2; /* increasing gap = 2 and 4 */int count = 3; /* no. of primes */int may_be_prime = 5; /* working variable */int i, is_prime;prime[0] = 2; /* Note that 2, 3 and 5 are */prime[1] = 3; /* primes. */prime[2] = 5;while (count < MAXSIZE) { /* loop until prime[] full*/may_be_prime += gap; /* get next number */gap = 6 - gap; /* switch to next gap */is_prime = YES; /* suppose it were a prime*/for (i = 2; prime[i]*prime[i] <= may_be_prime && is_prime; i++)if (may_be_prime % prime[i] == 0) /* NO */is_prime = NO; /* exit */if (is_prime) /* if it IS a prime... */prime[count++] = may_be_prime; /* save it */}printf("\nPrime Number Generation Program");printf("\n===============================\n");printf("\nFirst %d Prime Numbers are :\n", count);for (i = 0; i < count; i++) {if (i % 10 == 0) printf("\n");printf("%5d", prime[i]);} }
/* ------------------------------------------------------ */ /* FUNCTION sieve : */ /* This program uses Eratosthenes Sieve method to */ /* generate all primes between 2 and MAXSIZE*2+3. This */ /* is a very simple yet elegant method to generate primes */ /* */ /* Copyright Ching-Kuang Shene July/01/1989 */ /* ------------------------------------------------------ */#include <stdio.h>#define MAXSIZE 200 #define DELETED 1 #define KEPT 0void main(void) {int sieve[MAXSIZE+1]; /* the sieve array */int count = 1; /* no. of primes counter */int prime; /* a generated prime */int i, k; /* working variable */printf("\nEratosthenes Sieve Method");printf("\n=========================");printf("\n\nPrime Numbers between 2 and %d\n", MAXSIZE*2+3);for (i = 0; i <= MAXSIZE; i++) /* set all items to be*/sieve[i] = KEPT; /* kept in the sieve */for (i = 0; i <= MAXSIZE; i++) /* for each i, it */if (sieve[i] == KEPT) { /* corresponds to 2i+3*/prime = i + i + 3; /* if it is not sieved*/count++; /* prime=2i+3. */for (k = prime + i; k <= MAXSIZE; k += prime)sieve[k] = DELETED; /* screen multiple*/}printf("\n%6d", 2); /* output part. */for (i = 0, k = 2; i <= MAXSIZE; i++)if (sieve[i] == KEPT) {if (k > 10) {printf("\n");k = 1;}printf("%6d", 2*i+3);k++;}printf("\n\nThere are %d primes in total.", count); }
/* ------------------------------------------------------ */ /* PROGRAM linear sieve program of Gries and Misra : */ /* This program finds all prime numbers between 2 and */ /* n, the input, by using Gries and Misra linear sieve */ /* method. This method does not use division, instead */ /* multiplications are used. */ /* */ /* Copyright Ching-Kuang Shene July/10/1989 */ /* ------------------------------------------------------ */#include <stdio.h> #include <stdlib.h>#define MAXSIZE 1000 #define NEXT(x) x = next[x] #define REMOVE(x) { next[previous[x]] = next[x]; \previous[next[x]] = previous[x]; \} #define INITIAL(n) { unsigned long i; \for (i = 2; i <= n; i++) \previous[i] = i-1, next[i] = i+1;\previous[2] = next[n] = NULL; \}void main(void) {unsigned long previous[MAXSIZE+1]; /* prev. pointer */unsigned long next[MAXSIZE+1]; /* next pointer */unsigned long prime, fact, i, mult;unsigned long n;unsigned long count = 0;char line[100], dummy;printf("\nLinear Sieve Program");printf("\n====================");printf("\n\nPrime Numbers between 2 to --> ");gets(line);n = strtoul(line, &dummy, 10);INITIAL(n); /* initial the set */for (prime = 2; prime*prime <= n; NEXT(prime))for (fact = prime; prime*fact <= n; NEXT(fact))for (mult = prime*fact; mult <= n; mult *= prime)REMOVE(mult); /* remove multiples */for (i = 2; i != NULL; NEXT(i)) { /* display result */if (count % 8 == 0) printf("\n");printf("%6ld", i);count++;}printf("\n\nThere are %ld Prime Numbers in Total", count); }
/* ------------------------------------------------------ */ /* PROGRAM factorization of positive integers : */ /* Given un unsigned long integer, this program finds */ /* all prime factor by using traditional division method. */ /* */ /* Copyright Ching-Kuang Shene July/10/1989 */ /* ------------------------------------------------------ */#include <stdio.h> #include <stdlib.h>#define MAXSIZE 100 #define SAVE_FACTOR(fact, exp) { if (exp > 0) \factors[count] = fact, \exps[count++] = i; \}void main(void) {unsigned long factors[MAXSIZE]; /* stores factors */unsigned long exps[MAXSIZE]; /* stores exps */unsigned long n, work;int count = 0; /* factor counter */int i, k;char line[100], *dummy;printf("\nFactorization by Division Program");printf("\n=================================");printf("\n\nInput a positive integer --> ");gets(line);n = strtoul(line, &dummy, 10);for (i=0,work=n; (work & 0x01UL)==0 && work>1; work>>=1,i++); /* extract divisor 2 */SAVE_FACTOR(2, i); /* save it and its exp. */for (k = 3; k <= work; k += 2) { /* for k=3,5,7,9,.. */for (i = 0; work % k == 0 && work > 1; work /= k, i++); /* extract divisor k */SAVE_FACTOR(k, i); /* save it and its exp. */}printf("\n%ld = ", n); /* display result. */for (i = 0; i < count; i++)printf("%ld(%ld)", factors[i], exps[i]); }
unsigned long recursive_power(unsigned long m, unsigned long n) {unsigned long temp;if (n == 0) /* m^0 = 1 */return 1;else if (n & 0x01UL == 0) { /* if power is even then */temp = recursive_power(m, n >> 1); return temp * temp; /* m^(2k) = (m^k)^2 */}else /* otherwise, m^n=m*m^(n-1) */return m * recursive_power(m, n-1); }
unsigned long iterative_power(unsigned long m, unsigned long n) {unsigned long temp = 1;while (n > 0) { /* if there exists 1 bits.. */if (n & 0x01UL == 1)/* the right most one ? */temp *= m; /* YES, the result get a 'm'*/m *= m; /* anyway, compute m^k */n >>= 1; /* throw away this bit */}return temp; }
unsigned long fibonacci(int n) {unsigned long f0, f1, temp;int i;if (n <= 2)return 1;else {for (f0 = f1 = 1, i = 3; i <= n; i++) {temp = f0 + f1; /* temp = f(n-2)+f(n-1) */f0 = f1; /* f0 = f(n-2) */f1 = temp; /* f1 = f(n-1) */}return f1;} }
可以用这个观点来编写程序。
- void matrix_power(unsigned long, unsigned long,
- unsigned long, unsigned long, int,
- unsigned long *, unsigned long *,
- unsigned long *, unsigned long *);
- unsigned long fibonacci(int n)
- {
- unsigned long a, b, c, d;
- if (n <= 2)
- return 1;
- else { /* A^(n-2) of a matrix A */
- matrix_power(1UL, 1UL, 1UL, 0UL, n-2, &a, &b, &c, &d);
- return a + b;
- }
- }
- /* ------------------------------------------------------ */
- /* FUNCTION matrix_power : */
- /* This function accepts a matrix X and computes */
- /* X^(n-2) for n >= 3 using the power computation method, */
- /* where X is defined as follows */
- /* */
- /* +- -+ +- -+(n-2) */
- /* | aa bb | | a b | */
- /* | | = | | */
- /* | cc dd | | c d | */
- /* +- -+ +- -+ */
- /* ------------------------------------------------------ */
- void matrix_power(unsigned long a, unsigned long b,
- unsigned long c, unsigned long d, int n,
- unsigned long *aa, unsigned long *bb,
- unsigned long *cc, unsigned long *dd)
- {
- unsigned long xa, xb, xc, xd;
- if (n == 1)
- *aa = a, *bb = b, *cc = c, *dd = d;
- else if (n & 0x01 == 1) { /* n odd: X^(2k+1)=X*X^(2k)*/
- matrix_power(a, b, c, d, n-1, &xa, &xb, &xc, &xd);
- *aa = a*xa + b*xc;
- *bb = a*xb + b*xd;
- *cc = c*xa + d*xc;
- *dd = c*xb + d*xd;
- }
- else { /* n even: X^(2k)=(X^(2k))^2*/
- matrix_power(a, b, c, d, n>>1, &xa, &xb, &xc, &xd);
- *aa = xa*xa + xb*xc;
- *bb = xa*xb + xb*xd;
- *cc = xc*xa + xd*xc;
- *dd = xc*xb + xd*xd;
- }
- }
- /* ------------------------------------------------------ */
- #include <stdio.h>
- #include <stdlib.h> /* for function atoi() */
- void main(void)
- {
- char line[100];
- int n;
- printf("\nO(log(n)) Fibonacci Number Computation\n");
- printf("\nn please ---> ");
- gets(line);
- n = atoi(line);
- printf("\nfib(%d) = %lu", n, fibonacci(n));
- }
- unsigned long ext_fibonacci(int n, int x, int y)
- {
- unsigned long f0, f1;
- unsigned long a0, a1;
- unsigned long temp1, temp2;
- int i;
- if (n == 0)
- return 1;
- else if (n == 1)
- return 2;
- else {
- for (f0 = f1 = 1, a0 = 1, a1 = 2, i = 2; i <= n; i++) {
- temp1 = x*f1 + y*f0;
- f0 = f1;
- f1 = temp1;
- temp2 = x*a0 + y*(a1 - f0) + f0 + f1;
- a0 = a1;
- a1 = temp2;
- }
- return a1;
- }
- }
- /* ------------------------------------------------------ */
- #include <stdio.h>
- #include <stdlib.h>
- void main(void)
- {
- char line[100];
- int n, x, y;
- printf("\nExtended Fibonacci Number Computation\n");
- printf("\nGiven x and y, define the Extended Fibonacci"
- " Number as follows\n");
- printf("\nXfib(0) = 1; Xfib(1) = 1;"
- " Xfib(n) = x*Xfib(n-1) + y*Xfib(n-2)\n");
- printf("\nNow given another integer n, compute the sum of");
- printf("\nXfib(0)*Xfib(n) + Xfib(1)*Xfib(n-1) + ... +"
- " Xfib(i)*Xfib(n-i) + ... ");
- printf("\n + Xfib(n-1)*Xfib(1) + Xfib(n)*Xfib(0)\n");
- printf("\nx ---> ");
- gets(line);
- x = atoi(line);
- printf("\ny ---> ");
- gets(line);
- y = atoi(line);
- printf("\nn ---> ");
- gets(line);
- n = atoi(line);
- printf("\n\nAnswer is %lu", ext_fibonacci(n, x, y));
- }
- #define MAXSIZE 100
- unsigned long cnr(int n, int r)
- {
- unsigned long c[MAXSIZE];
- int i, j;
- for (i = 0; i <= r; i++) /* initial c[] to all 1's */
- c[i] = 1UL;
- for (i = 1; i <= n-r; i++) /* compute C(n,r) by add. */
- for (j = 1; j <= r; j++) /* but compute only */
- c[j] += c[j-1]; /* those needed. */
- return c[r];
- }
如果使用的语言或编译程序(如Ada)有可以计算任意位整数加、减、乘、除的能力 的话,能够从这个式子找出一个只需要与化成正比的乘法次数求所有C(n,i),i=0,l,…,n
/* --------------------------------------------------------- */ /* FUNCTION cnr : */ /* A special function to calculate all C(n,r)'s given n. */ /* It employs a very special trick on bit operations. NOTE */ /* that depend on the number of bits for unsigned long type */ /* this function might returns wrong answer. The rule of */ /* thumb is that if unsigned long has k bits then the max. */ /* of n, the input, should be no more than following : */ /* */ /* -1 + sqrt(1 + 4*k) */ /* -------------------- */ /* 2 */ /* */ /* Thus for k=32 as many microprocessor has, then the max. */ /* of n is 5. But this should not be viewd as a restriction */ /* because the same algorithm can be used in more advanced */ /* non-numeric applications. */ /* */ /* Copyright Ching-Kuang SHENE Feb/24/1989 */ /* --------------------------------------------------------- */unsigned long power(unsigned long, unsigned long);void cnr(int n, int answer[]) {unsigned long x = (1 << n) + 1; /* 2^n + 1 */unsigned long mask = (1 << n) - 1; /* 2^n - 1, n 1's */unsigned long result;int i;result = power(x, (unsigned long) n); /* (2^n+1)^n */for (i = 0; i <= n; i++, result >>= n) /* retrieve data */answer[i] = result & mask; }/* ------------------------------------------------------ */ /* FUNCTION power : */ /* This is the function called 'iterative_power' in */ /* file I_POWER.C of this book. */ /* ------------------------------------------------------ */unsigned long power(unsigned long m, unsigned long n) {unsigned long temp = 1;while (n > 0) { /* if there exists 1 bits.. */if (n & 0x01UL == 1)/* the right most one ? */temp *= m; /* YES, the result get a 'm'*/m *= m; /* anyway, compute m^k */n >>= 1; /* throw away this bit */}return temp; }/* ------------------------------------------------------ */#include <stdio.h> #include <stdlib.h>#define MAXSIZE 10void main(void) {int answer[MAXSIZE];int n, r;char line[100];printf("\nFast Combinatorial Coefficient Computation");printf("\n==========================================");printf("\n\nN ---> ");gets(line);n = atoi(line);cnr(n, answer);printf("\nAll Combinatorial Coefficients :\n");for (r = 0; r <= n; r++)printf("\nC(%d,%d) = %d", n, r, answer[r]); }
个乘法,因此能不能用某个C(n,i)来帮忙算n!呢?
- unsigned long power(unsigned long, unsigned long);
- void cnr(int n, int answer[])
- {
- unsigned long x = (1 << n) + 1; /* 2^n + 1 */
- unsigned long mask = (1 << n) - 1; /* 2^n - 1, n 1's */
- unsigned long result;
- int i;
- result = power(x, (unsigned long) n); /* (2^n+1)^n */
- for (i = 0; i <= n; i++, result >>= n) /* retrieve data */
- answer[i] = result & mask;
- }
- /* ------------------------------------------------------ */
- /* FUNCTION power : */
- /* This is the function called 'iterative_power' in */
- /* file I_POWER.C of this book. */
- /* ------------------------------------------------------ */
- unsigned long power(unsigned long m, unsigned long n)
- {
- unsigned long temp = 1;
- while (n > 0) { /* if there exists 1 bits.. */
- if (n & 0x01UL == 1)/* the right most one ? */
- temp *= m; /* YES, the result get a 'm'*/
- m *= m; /* anyway, compute m^k */
- n >>= 1; /* throw away this bit */
- }
- return temp;
- }
- /* ------------------------------------------------------ */
- #include <stdio.h>
- #include <stdlib.h>
- #define MAXSIZE 10
- void main(void)
- {
- int answer[MAXSIZE];
- int n, r;
- char line[100];
- printf("\nFast Combinatorial Coefficient Computation");
- printf("\n==========================================");
- printf("\n\nN ---> ");
- gets(line);
- n = atoi(line);
- cnr(n, answer);
- printf("\nAll Combinatorial Coefficients :\n");
- for (r = 0; r <= n; r++)
- printf("\nC(%d,%d) = %d", n, r, answer[r]);
- }
- unsigned long mask; /* mask for shifting bits */
- unsigned cnrs[100]; /* storage for C(n,n/2)'s */
- int number; /* index for cnrs[] */
- int p_size; /* partition size in C(n,n/2) */
- unsigned long factor(unsigned long);
- unsigned long power(unsigned long, unsigned long);
- /* -------------------------------------------------------- */
- /* FUNCTION factorial : */
- /* Control routine of n! calculation. */
- /* -------------------------------------------------------- */
- unsigned long factorial(unsigned long n)
- {
- unsigned long x = (1 << n) + 1;
- number = 0; /* set index to init. pos. */
- mask = (1 << n) - 1; /* set up mask for shifting */
- p_size = n; /* set up partition size */
- (void) power(x, n); /* now computing (2^n+1)^n */
- number = 0; /* reset index to the start */
- return factor(n); /* then compute n! */
- }
- /* -------------------------------------------------------- */
- /* FUNCTION factor : */
- /* This is the working routine for n!. The idea is */
- /* */
- /* +- 1 if n = 1 */
- /* | */
- /* n! = + n * (n-1)! if n is odd */
- /* | */
- /* +- C(n,n/2)*[(n/2)]! if n is even */
- /* */
- /* Before factor() is called n_power() is used to compute */
- /* (2^n+1)^n and during the course of this computation, it */
- /* stores all relevant C(n,n/2) into array cnrs[]. Thus */
- /* C(n,n/2)'s are available from array C(n,n/2) here. */
- /* -------------------------------------------------------- */
- unsigned long factor(unsigned long n)
- {
- unsigned long temp;
- if (n == 1)
- return 1;
- else if (n & 0x01UL == 1)
- return n * factor(n - 1);
- else {
- temp = factor(n >> 1);
- return cnrs[number++] * temp * temp;
- }
- }
- /* -------------------------------------------------------- */
- /* FUNCTION power : */
- /* The modified power function to compute (2^n+1)^n in */
- /* recursive mode. During its computation, n_power() will */
- /* save C(n,n/2) into array cnrs[]. */
- /* -------------------------------------------------------- */
- unsigned long power(unsigned long n, unsigned long m)
- {
- unsigned long temp;
- if (m == 1)
- temp = n;
- else if (m & 0x01UL != 0)
- temp = n * power(n, m-1);
- else {
- temp = power(n, m >> 1);
- temp *= temp;
- cnrs[number++] = (temp >> ((m >> 1)*p_size)) & mask;
- }
- return temp;
- }
- /* -------------------------------------------------------- */
- #include <stdio.h>
- #include <stdlib.h> /* for strtoul() function */
- void main(void)
- {
- char line[100], *dummy_ptr;
- unsigned long m, n;
- printf("\nThe Fast N! Computation :");
- printf("\n\nN for N! please --> ");
- gets(line);
- n = strtoul(line, &dummy_ptr, 10);
- printf("\n%lu! = %lu", n, factorial(n));
- }
- #include <stdio.h>
- #include <stdlib.h>
- void main(void)
- {
- long left, right; /* left and right bound */
- long sum; /* computed sum */
- long GIVEN; /* the given number */
- int count = 0; /* solution counter */
- char line[100]; /* input buffer */
- printf("\nConsecutive sum to a fixed given number");
- printf("\n=======================================\n");
- printf("\nYour number (> 0) please ---> ");
- gets(line);
- GIVEN = atol(line);
- for (sum = 0, right = 1; sum < GIVEN; sum += right, right++)
- ;
- for (left = 1, right--; left <= GIVEN/2; )
- if (sum > GIVEN) /* if sum too large */
- sum -= (left++); /* reduce from left */
- else {
- if (sum == GIVEN) { /* if equal, print it */
- printf("\n%ld = sum from %ld to %ld",
- GIVEN, left, right);
- count++; /* and increase count */
- } /* if sum too small */
- sum += (++right); /* increase from right */
- }
- if (count > 0)
- printf("\n\nThere are %d solutions in total.", count);
- else
- printf("\n\nSorry, there is NO solution at all.");
- }
C语言名题精选百则——数字问题相关推荐
- c语言名题精选百则,Victor's Log
我用的操作系统 (此文发在紫丁香BBS的Linux版) 我昨天一时兴起,转发了这篇文章(注:王垠的<完全用Linux工作,摈弃Windows>).我说说我的看法和想法.在我的印象里,使用U ...
- 《C语言名题精选百则----8》
题目不是很难,但是像这本书上大部分的题目一样,解决很容易,但是写好很难. 先上我的答案:(源码无法正常显示的话就点击右键->查看源文件) #include<stdio.h>void ...
- 高中信息技术c语言编程题,高中信息技术招聘C语言编程题精选.doc
C语言编程题精选 编程实现对键盘输入的英文名句子进行加密.用加密方法为,当内容为英文字母时其在26字母中的其后三个字母代替该字母,若为其它字符时不变. 编程实现将任意的十进制整数转换成R进制数(R在2 ...
- c语言编程模拟选举,C语言编程题精选
C语言编程题精选 C语言编程题精选 1. 编程实现对键盘输入的英文名句子进行加密.用加密方法为,当内容为英文字母时其在26字母中的其后三个字母代替该字母,若为其它字符时不变. 2. 编程实现将任意的十 ...
- c语言作文的题目_高中信息技术招聘C语言编程题精选
C 语言编程题精选 1 .编程实现对键盘输入的英文名句子进行加密.用加密方法为,当内容为英文字母时其 在 26 字母中的其后三个字母代替该字母,若为其它字符时不变. 2 . 编程实现将任意的十进制整数 ...
- 高中信息技术c语言编程题,高中信息技术招聘C语言编程题精选.pdf
高中信息技术招聘C语言编程题精选 C语言编程题精选 1.编程实现对键盘输入的英文名句子进行加密.用加密方法为,当内容为英文字母时其 在26字母中的其后三个字母代替该字母,若为其它字符时不变. 2.编程 ...
- c语言代码题及答案,c语言编程题精选及答案
c语言编程题精选及答案 C 语言编程题精选 C 语言学习 2010-11-30 15:48:25 阅读 47 评论 0 字号:大中小 订阅 1. 有函数 F(x)=(x+1)2 和 G(x)=2x+1 ...
- char转化为cstring_C语言100题集合001-将一个数字字符串转换为一个整数
系列文章<C语言经典100例>持续创作中,欢迎大家的关注和支持. 喜欢的同学记得点赞收藏哦- 1 题目 题目:将一个数字字符串转换为一个整数(不得调用C语言中提供的字符串函数进行操作) 例 ...
- 菜niao鸟教程C语言100题精选
以下题目是从菜鸟教程网站挑选出的.C 语言经典100例 | 菜鸟教程 (runoob.com) 第29题(将数分解) 我的做法,用递归函数. #include<stdio.h>int ma ...
最新文章
- 组网中交换机虚拟化技术的应用
- 内网穿透从搭建到溯源
- 【转】 关于寄存器ESP和EBP的一些理解
- cassss服务未启动_电梯启动死机故障处理方法
- java抽象类泛型_java-使用泛型定义抽象方法
- Android的异步多线程消息处理机制
- Cobbler批量装机
- 微信emoji表情数据如何添加到json中
- 安卓dj专业打碟机软件_学DJ打碟必备设备
- 考研基础高等数学笔记
- RS码的噪声误码率图matlab,QPSK系统的误码率和星座图MATLAB仿真
- 路由器带硬盘+文件服务器,还买什么NAS 一台带有USB3.0的路由器解决家庭存储共享...
- 三、mono for android 学习:参考书籍
- linux下显卡信息的查看
- 两种方法分割python多空格字符串
- 使用决策树预测大盘指数
- 东大22春《计算机应用基础》在线平时作业3_100分参考非答案
- 盘点2016最值得突击的七大海外市场:最后一年窗口期,不出海就出局!
- 计算机不识别lacie硬盘,LaCie移动硬盘
- Android技术功底不够如何去面试,复习指南
热门文章
- MarkDown文本首行怎么缩进?
- 百度地图BMap is not defined(Bmap未定义)
- 子曾经曰过,玩笑不能乱开。
- html鼠标滑过导航条展开导航条,JS+CSS实现鼠标滑过时动态翻滚的导航条效果
- 美国“求包养”网站注册会员已超过100万人
- HTML5和CSS3自我学习认知基础知识
- OpenGov(一):什么是Polkadot Gov2
- 梳子刻字刻什么好_校园石阶上被刻了1700多个汉字,这次网友却说好
- 二元运算符重载 must take either zero or one argument
- prezi中文输入法使用教程