記事ディレクトリ
確認実験
1からnまでの連続する整数の合計を求めます
説明する
与えられた正の整数nについて、1 +2+…+n1 + 2+…+nを見つけます1+2+…+n、累積合計を使用n(n + 1)2 \ frac {n(n + 1)} 22n (n +1)(ガウスの方法)2つの解決策。
同じnについて、これら2つの解の合計結果と解時間が与えられ、関連するデータでテストされます。
- clock_tタイプ、clock()関数、およびCLOCKS_PER_SEC定数は、time.hヘッダーファイルで宣言されています。
- clock_tは、クロックデータ型(long)です。
- clock()関数は、CPUクロックティック数(ミリ秒単位)を返します。
- CLOCKSPER_SECは、1秒に含まれるミリ秒数を表す定数です。
- 式((float)t)/ CLOCKS_PER_SECは、tから変換された秒数を返します。
グレーディング
//文件名:exp1-1.cpp
//求1+2+...+n
#include <stdio.h>
#include <time.h> // clock_t, clock, CLOCKS_PER_SEC
#include <math.h>
//方法1:老实累加
long add1(long n)
{
long i, sum = 0;
for (i = 1; i <= n; i++)
sum += i;
return(sum);
}
void AddTime1(long n) /* 采用方法1的耗时统计 */
{
clock_t t = clock();
long sum = add1(n);
t = clock() - t;
printf("方法1:\n");
printf(" 结果:1~%d之和:%ld\n", n, sum);
printf(" 用时:%lf秒\n", ((float)t) / CLOCKS_PER_SEC);
}
//方法2:用公式
long add2(long n) /* 方法2:求1+2+...+n */
{
return(n * (n + 1) / 2);
}
void AddTime2(long n) /* 采用方法2的耗时统计 */
{
clock_t t = clock();
long sum = add2(n);
t = clock() - t;
printf("方法2:\n");
printf(" 结果:1~%d之和:%ld\n", n, sum);
printf(" 用时:%lf秒\n", ((float)t) / CLOCKS_PER_SEC);
}
int main()
{
int n;
printf("n(大于1000000):");
scanf("%d", &n);
if (n < 1000000)
return(0);
AddTime1(n);
AddTime2(n);
return(1);
}
結果
n(大于1000000):99999999
方法1:
结果:1~99999999之和:887459712
用时:0.222000秒
方法2:
结果:1~99999999之和:887459712
用时:0.000000秒
请按任意键继续. . .
一般的なアルゴリズムの時間関数の成長傾向分析
説明する
一般的なアルゴリズムの時間関数の成長を理解します。
1からnまでの整数nごとに、log2n\log_2nと入力します。lo g2n n\ sqrt nn。、nnn、nlog2nn \ log_2nnlo g2n、n 2 n ^ 2n2、n 3 n ^ 3n3、2 n2 ^ n2nとn!n!n !。
グレーディング
//文件名:exp1-2.cpp
#include <stdio.h>
#include <math.h>
double log2(double x) //求log2(x)
{
return log10(x)/log10((double)2);
}
long exponent(int n) //求2^n
{
long s=1;
for (int i=1;i<=n;i++)
s*=2;
return s;
}
long factorial(int n) //求n!
{
long s=1;
for (int i=1;i<=n;i++)
s*=i;
return s;
}
void fun(int n)
{
printf("log2(n) sqrt(n) n nlog2(n) n^2 n^3 2^n n!\n");
printf("===========================================================================\n");
for (int i=1;i<=n;i++)
{
printf("%5.2f\t",log2(double(i)));
printf("%5.2f\t",sqrt((double)i));
printf("%2d\t",i);
printf("%7.2f\t",i*log2(double(i)));
printf("%5d\t",i*i);
printf("%7d\t",i*i*i);
printf("%8d\t",exponent(i));
printf("%10d\n",factorial(i));
}
}
int main()
{
int n=10;
fun(n);
return 1;
}
結果
log2(n) sqrt(n) n nlog2(n) n^2 n^3 2^n n!
===========================================================================
0.00 1.00 1 0.00 1 1 2 1
1.00 1.41 2 2.00 4 8 4 2
1.58 1.73 3 4.75 9 27 8 6
2.00 2.00 4 8.00 16 64 16 24
2.32 2.24 5 11.61 25 125 32 120
2.58 2.45 6 15.51 36 216 64 720
2.81 2.65 7 19.65 49 343 128 5040
3.00 2.83 8 24.00 64 512 256 40320
3.17 3.00 9 28.53 81 729 512 362880
3.32 3.16 10 33.22 100 1000 1024 3628800
请按任意键继续. . .
計画実験
素数を探す
説明する
同じ問題に対するさまざまなソリューションの絶対実行時間を比較することで、「優れた」アルゴリズムを設計する方法を体験できます。
1からnまでの素数の数を見つけます。同じnについて、2つのソリューションの結果とソリューション時間が与えられ、関連するデータでテストされます。
グレーディング
//文件名:exp1-3.cpp
#include <stdio.h>
#include <stdlib.h>
#include <time.h> //clock_t, clock, CLOCKS_PER_SEC
#include <math.h>
//------方法1-----------------------------------------------
bool prime1(long n) //方法1:判断正整数n是否为素数
{
long i;
for (i = 2; i < n; i++)
if (n % i == 0)
return false; //若n不是素数,则退出并返回false
return true;
}
void PrimeTime1(long n) //采用方法1的耗时统计
{
long sum = 0, i;
clock_t t = clock();
for (i = 2; i <= n; i++)
if (prime1(i))
sum++;
t = clock() - t;
printf("方法1:\n");
printf(" 结果:2~%d的素数个数:%d\n", n, sum);
printf(" 用时:%lf秒\n", ((float)t) / CLOCKS_PER_SEC);
}
//------方法2-----------------------------------------------
bool prime2(long n) //方法2:判断正整数n是否为素数
{
long i;
for (i = 2; i <= (int)sqrt((double)n); i++)//对n开方进行优化
if (n % i == 0)
return false; //若n不是素数,则退出并返回false
return true;
}
void PrimeTime2(long n) //采用方法2的耗时统计
{
long sum = 0, i;
clock_t t = clock();
for (i = 2; i <= n; i++)
if (prime2(i))
sum++;
t = clock() - t;
printf("方法2:\n");
printf(" 结果:2~%d的素数个数:%d\n", n, sum);
printf(" 用时:%lf秒\n", ((float)t) / CLOCKS_PER_SEC);
}
//------方法3-----------------------------------------------
int countPrimes(long n) //方法3:埃拉托色尼筛选法,空间换时间,n不能过大,否则程序报错
{
bool *flag = (bool *)malloc(n * sizeof(bool));
for (long i = 0; i < n; i++)//这步不能省略,否则得不到正确值
flag[i] = 0;
int count = 0;
for (long i = 2; i < n; i++){
if (flag[i] == 0){
count++;
for (long j = i; i * j < n; j++) {
flag[i * j] = 1;
}
}
}
free(flag);
return count;
}
void PrimeTime3(long n) //采用方法3的耗时统计
{
long sum = 0;
clock_t t = clock();
sum = countPrimes(n);
t = clock() - t;
printf("方法3:\n");
printf(" 结果:2~%d的素数个数:%d\n", n, sum);
printf(" 用时:%lf秒\n", ((float)t) / CLOCKS_PER_SEC);
}
//------------------------------------------------------------
int main() {
long n;
printf("n(取值范围[10000, 40000]):");
scanf("%d", &n);
if (!(10000 <= n && n <= 40000)) return 0;
PrimeTime1(n);
PrimeTime2(n);
PrimeTime3(n);
return 1;
}
結果
n(取值范围[10000, 40000]):40000
方法1:
结果:2~40000的素数个数:4203
用时:0.236000秒
方法2:
结果:2~40000的素数个数:4203
用时:0.009000秒
方法3:
结果:2~40000的素数个数:4203
用时:0.001000秒
请按任意键继续. . .
連続する整数の階乗の合計を求めます
説明する
与えられた正の整数nに対して、1!+ 2!+ 3!+…+ n!を見つけます。時間計算量O(n)の解を与えます。
グレーディング
//文件名:exp1-4.cpp
#include <stdio.h>
//循环版
long Sum(int n) {
long sum = 0, fact = 1;
for (int i = 1; i <= n; i++) {
fact *= i;
sum += fact;
}
return sum;
}
//TODO:递归版
//------------------------------------------------------------
int main() {
int n;
printf("n(3-20):");
scanf("%d", &n);
if (n < 3 || n > 20) return 0;
printf("1!+2!+…+%d!=%ld\n", n, Sum(n));
return 1;
}
結果
n(3-20):15
1!+2!+…+15!=1443297817
请按任意键继续. . .