実験レポートのアルゴリズムの設計と解析

実験的なデザインと動作アルゴリズムは、一連の表し
https://www.cnblogs.com/31415926535x/p/10963938.htmlを

実験の目的

処理アルゴリズムとさらにお馴染みの、実験を理解し、再帰的な除算の基本的な考え方を習得して、アルゴリズムと貪欲アルゴリズムと特定の問題を解決する能力を征服、Cの++による問題解決のプロセスを達成するためには、この経験を通して。

ウェブテスト

:実験は、大きく3つの部分に分け概要再帰と分割統治戦略貪欲アルゴリズム問題の種類ごとに、約少なくとも一つの被写体とアルゴリズムの正しさを検証するためにコードを使用し、アルゴリズムの実現可能性を分析します。

アウトライン

統計の問題

タイトル

问题描述:

  一本书的页码从自然数1 开始顺序编码直到自然数n。书的页码按照通常的习惯编排,每个页码都不含多余的前导数字0。例如,第6 页用数字6 表示,而不是06 或006 等。数字计数问题要求对给定书的总页码n,计算出书的全部页码中分别用到多少次数字0,1, 2,…,9。

编程任务:

  给定表示书的总页码的10 进制整数n (1≤n≤109) 。编程计算书的全部页码中分别用到多少次数字0,1,2,…,9。

数据输入:

  输入数据由文件名为input.txt 的文本文件提供。每个文件只有1 行,给出表示书的总页码的整数n。

结果输出: 

  程序运行结束时,将计算结果输出到文件output.txt 中。输出文件共有10 行,在第k 行输出页码中用到数字k-1 的次数,k=1,2,…,10。

输入文件示例         
input.txt  
11
输出文件示例
output.txt 
1 
4 
1 
1 
1 
1 
1 
1 
1 
1 

アルゴリズムの考え方

各デジタル数がために発生する10ビット整数格納された配列のサイズ\(1 \ SIM N \)すべての数が発生し、最後の桁は、数で、最終的な出力の全てを取得している\ (0 \ SIM 9 \)番号に番号。

実験手順

#include <bits/stdc++.h>
using namespace std;
const int maxn = 10;
int a[maxn];
void solve(int n)
{
    while(n)
    {
        ++a[n % 10];
        n /= 10;
    }
    return;
}
int main()
{
    freopen("input.txt", "r", stdin);
    freopen("output.txt", "w", stdout);
    int n;
    scanf("%d", &n);
    memset(a, 0, sizeof a);
    for(int i = 1; i <= n; ++i)solve(i);
    for(int i = 0; i <= 9; ++i)printf("%d\n", a[i]);
}

テスト結果

input:
11

output:
1 
4 
1 
1 
1 
1 
1 
1 
1 
1 

質問の最大数について

タイトル

问题描述:

  正整数x 的约数是能整除x 的正整数。正整数x 的约数个数记为div(x) 。例如,1,2, 5,10 都是正整数10 的约数,且div(10)=4 。设a 和b 是2 个正整数,a≤b,找出a 和b 之间约数个数最多的数x。

编程任务:

  对于给定的2 个正整数a≤b,编程计算a 和b 之间约数个数最多的数。

数据输入:

  输入数据由文件名为input.txt 的文本文件提供。文件的第1 行有2 个正整数a 和b。

结果输出: 

  程序运行结束时,若找到的a 和b 之间约数个数最多的数是x,将div(x)输出到文件output.txt 中。

输入文件示例                输出文件示例
input.txt                   output.txt 
 1 36                             9 

アルゴリズムの考え方

前処理は全て\(1 \ SIM MAXN \)番号の各要素の数、および各試験トラバーサル\(A \シムB \)を出力する要素の最大数を同定します。

実験手順

#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e5 + 5;
int a[maxn];
void init()
{
    for(int i = 2; i <= maxn; ++i)
        for(int j = i; j <= maxn; j += i)
            ++a[j];
    return;
}
int main()
{
    // freopen("input.in", "r", stdin);
    // freopen("output.out", "w", stdout);
    init();
    int l, r;
    while(~scanf("%d%d", &l, &r))
    {
        int ans = 0;
        for(int i = l; i <= r; ++i)
            ans = max(ans, a[i]);
        printf("%d\n", ++ans);
    }
}

テスト結果

input.txt                   output.txt 
 1 36                             9 

辞書順の問題

タイトル

问题描述:

  在数据加密和数据压缩中常需要对特殊的字符串进行编码。给定的字母表A 由26 个小写英文字母组成A={a,b,…,z}。该字母表产生的升序字符串是指字符串中字母按照从左到右出现的次序与字母在字母表中出现的次序相同,且每个字符最多出现1 次。例如,a,b,ab,bc,xyz 等字符串都是升序字符串。现在对字母表A 产生的所有长度不超过6 的升序字符串按照字典序排列并编码如下。
1 2 
… 
26 27 28 
… 
a b 
… 
z ab ac 
… 
对任意长度不超过6 的升序字符串,迅速计算出它在上述字典中的编码。

编程任务:

  对于给定的长度不超过6 的升序字符串,编程计算出它在上述字典中的编码。

数据输入:
输入数据由文件名为input.txt 的文本文件提供文件的第一行是一个正整数k,表示接下来共有k 行接下来的k 行中,每行给出一个字符串。

结果输出: 

  程序运行结束时,将计算结果输出到文件output.txt 中。文件共有k 行,每行对应于一
个字符串的编码。
 
输入文件示例       输出文件示例
input.txt           output.txt 
2                      1 
a                      2 
b 

アルゴリズムの考え方

法律再帰的加算セグメントを見つけるための方法であって

複数の文字列の手のリリース番号を見ることができたら、それはで、数文字列が必要です\(K-1を得長い文字列+辞書電流要件の最初の文字の文字列の最後の数小さな、文字列と\の数の残りの文字に対応する同じ長さ+長さマイナス1と同じ)の列の全ての数を必要とする文字列の数を得るためには、一般的なコンピューティングは、明らかに存在する3つの動作:シーク文字列との最初の文字列の長さlenの数の全ての定義された\(SUM(k)は\)明らかに、すべての長さによって、初めとして、長さkの文字列の文字数を表します(\ K - 1 \)文字でスプライスさを得ることができるよりも大きくなるように、文字の先頭に、我々はの長さを見つける\を(K - 1 \)で始まり、\は、(A + 1 \シム26 \) すべての文字列の数であります我々は長得ることができる\(K \)と、文字列の番号の先頭に、すなわち:\(SUM(K)= \ sum_ {i}は+を= 1} ^ {SUM 26は、(私は、1-K)\) これは再帰的な方法によって得ることができます。

だから、全体の問題は、プロセスの結果です:

  • 文字列は、K-1の数(この場合は文字全て始まる)26は、和()を呼び出し関数の全てに対して計算されます
  • 文字の長さは文字列kの文字の文字列の先頭に必要なよりも小さくなるように計算されてすべてが始まります。call \(1 \)回の合計()関数を
  • 長さを計算\(K-1 \)を、要求に対応する文字列のそれよりも小さくなるように、いくつかの文字列が続くと

例えば:

S:cefvz

  • 最初の数5未満のすべての決定の長さの、即ち:\(「A」\ SIM \「WXYZ」\)番号
  • 取得\を(「ABCDE」\ SIM \ 「bwxyz」\) このセクションの数は、文字列の「C」よりも小さい始め、5の長さを計算することです
  • 取得\(「CDEFG」\ SIM \ 「cefvz」\) このセクションの数は、k 1 = 4の「efvz」にすべての文字列「DEFG」の数の長さを計算することです
ハッシュ辞書の保存2.暴力行為深い検索

わずか6所与のタイトル文字列の必要な最大長は、検索結果の文字列が修飾すべての深いことができるので、(DFSは、文字列のシーケンス番号である)、次に、ハッシュ値列を所定のそれぞれについて、最後に、数値のハッシュ文字列に基づいて、各照会のために導くことができます。(試験データは、この方法により生成することができます)

実験手順

第1幕
#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e5;
char s[10];

int sum(int i, int j)
{
    int ret = 0;
    if(j == 1)return 1;
    else
    {
        for(int k = i + 1; k <= 26; ++k)
            ret += sum(k, j - 1);
    }
    return ret;
}
void solve()
{
    int ans = 0;
    int len = strlen(s);
    for(int i = 1; i <= len - 1; ++i)
        for(int j = 1; j <= 26; ++j)
            ans += sum(j, i);
    // cout << ans << "--" << endl;
    for(int i = 1; i <= s[0] - 'a' + 1 - 1; ++i)
        ans += sum(i, len);
    // cout << ans << "--" << endl;
    for(int i = 1; i <= len - 1; ++i)
    {
        for(int j = s[i - 1] - 'a' + 1 + 1; j <= s[i] - 'a' + 1 - 1; ++j)
            ans += sum(j, len - i);
    }
    printf("%d\n", ++ans);
}

int main()
{
//    freopen("input.txt", "r", stdin);
//    freopen("output.txt", "w", stdout);

    int t;scanf("%d", &t);
    while(t--)
    {
        scanf("%s", &s);
        solve();
    }
    return 0;
}
第2幕
#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e5;
char s[10];
const int p = 1e3+7;
unordered_map<int, int> mp;
inline int gethash(int len)
{
    int ret = 1;
    for(int i = 0; i <= len - 1; ++i)
        ret += ret * p + s[i] - 'a';
    return ret;
}
int tot = 0;
void print(int len, int n)
{
    if(n == len)
    {
//        printf("%s", s);
        // for(int i = 0; i < len; ++i)printf("%c", s[i]);
        // printf("\n");
        mp[gethash(len)] = ++tot;
        return;
    }
    if(n == 0)
    {
        for(int i = 0; i < 26; ++i)
        {
            s[0] = (char)(i + 'a');
            print(len, n + 1);
        }
    }
    else
    {
        for(int i = 0; i < 26; ++i)
        {
            if(s[n - 1] < i + 'a')
            {
                s[n] = (char)(i + 'a');
                print(len, n + 1);
            }
        }

    }

    return;
}
void init()
{
    tot = 0;
    for(int i = 1; i <= 6; ++i)
        print(i, 0);
}

int main()
{
//    freopen("input.txt", "r", stdin);
//    freopen("output.txt", "w", stdout);

    init();
    int t;scanf("%d", &t);
    while(t--)
    {
        scanf("%s", &s);
        printf("%d\n", mp[gethash(strlen(s))]);
    }
    return 0;
}

テスト結果

input:
4
abc
bciop
acfuxz
uvwxyz

output:
352
31577
98306
313911

貪欲アルゴリズム

ストレージ手続き

タイトル

算法实现题     程序存储问题

问题描述:

  设有n 个程序{1,2,…, n }要存放在长度为L 的磁带上。程序i 存放在磁带上的长度是li,1≤i≤n 。程序存储问题要求确定这n 个程序在磁带上的一个存储方案,使得能够在磁带上存储尽可能多的程序。

编程任务:

  对于给定的n 个程序存放在磁带上的长度,编程计算磁带上最多可以存储的程序数。

数据输入:

  由文件input.txt 给出输入数据。第一行是2 个正整数,分别表示文件个数n 和磁带的长度L。接下来的1 行中,有n 个正整数,表示程序存放在磁带上的长度。

结果输出: 

  将编程计算出的最多可以存储的程序数输出到文件output.txt 。

输入文件示例输出文件示例
input.txt                        output.txt 
6 50                                  5
2 3 13 8 80 20

アルゴリズムの考え方

あなたは、ストレージの数を最大化したいので、その小さな収納スペースに優先権を与えます。

ソーティング及びスペースの最大数よりも少ないだけに等しい前方空間を取った後。

実験手順

#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e5;
int a[maxn];
void solve()
{
    int n, l;
    scanf("%d%d", &n, &l);
    for(int i = 1; i <= n; ++i)scanf("%d", &a[i]);
    sort(a + 1, a + 1 + n);
    int ans = 0;
    int sum = 0;
    for(int i = 1; i <= n; ++i)
    {
        sum += a[i];
        if(sum <= l)++ans;
        else break;
    }
    printf("%d\n", ans);
    return;
}
int main()
{
//    freopen("input.txt", "r", stdin);
//    freopen("output.txt", "w", stdout);

    solve();
    return 0;
}

テスト結果

input:
6 50                                 
2 3 13 8 80 20

output:
5

車の給油

タイトル

算法实现题    汽车加油问题

问题描述:

  一辆汽车加满油后可行驶n 公里。旅途中有若干个加油站。设计一个有效算法,指出应在哪些加油站停靠加油,使沿途加油次数最少。并证明算法能产生一个最优解。

编程任务:

  对于给定的n 和k 个加油站位置,编程计算最少加油次数。

数据输入:

  由文件input.txt 给出输入数据。第一行有2 个正整数n 和k,表示汽车加满油后可行驶n 公里,且旅途中有k 个加油站。接下来的1 行中,有k+1 个整数,表示第k 个加油站与第k-1 个加油站之间的距离。第0 个加油站表示出发地,汽车已加满油。第k+1 个加油站表示目的地。

结果输出: 

  将编程计算出的最少加油次数输出到文件output.txt 。如果无法到达目的地,则输出”No Solution”。

输入文件示例输出文件示例
input.txt                       output.txt 
7 7                                  4
1 2 3 4 5 1 6 6

アルゴリズムの考え方

現在は次の停留所でのガソリンスタンドに到達、またはすべての道を行くために、残りの十分な燃料がないときに貪欲では、給油を考えます。

実験手順

#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e5;
int n, k, a[maxn];
int main()
{
    // freopen("input.txt", "r", stdin);
    // freopen("output.txt", "w", stdout);
    cin >> n >> k;
    for(int i = 0; i <= k; ++i)cin >> a[i];
    int ans = 0;
    for(int i = 1; i <= k; ++i)
    {
        int sum = 0;
        int nxt = i;
        for(nxt = i; nxt <= k; ++nxt)
        {
            sum += a[nxt];
            if(sum > n)break;
        }
        if(i == nxt)
        {
            cout << "No Solution" << endl;
            return 0;
        }
        i = nxt - 1;
        ++ans;
        if(nxt == k + 1)break;
    }
    cout << ans - 1 << endl;
    return 0;
}

テスト結果

input:
7 7
1 2 3 4 5 1 6 6

output;
4

最適な分解問題

タイトル

算法实现    最优分解问题

问题描述:

  设n 是一个正整数。现在要求将n 分解为若干个互不相同的自然数的和,且使这些自然数的乘积最大。

编程任务:

  对于给定的正整数n,编程计算最优分解方案。

数据输入:

  由文件input.txt 提供输入数据。文件的第1 行是正整数n。

结果输出: 

  程序运行结束时,将计算出的最大乘积输出到文件output.txt 中。

输入文件示例         输出文件示例
input.txt            output.txt 
10                      30 

アルゴリズムの考え方

場合\は(N = I J \ +) \(\のIJ)が非常に近い場合、\(iはj個の\を*)最大n個に分解最初の\(= {2 + 3 + 4 +です。 .. + K} \)\(\ SUM <= N \)後方増刊、プラスすべてのための1つの部分は、最大の最終生成物が保証します。

実験手順

#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e5 + 5;
int a[maxn];
int n;
void solve()
{
    for(int i = 1; i * i / 4 <= n; ++i)
        a[i] = i;
    int sum = 0;
    int last;
    for(int i = 2; i * i / 4 <= n; ++i)
    {
        sum += a[i];
        if(sum >= n)
        {
            sum -= a[i];
            sum = n - sum;
            last = i - 1;
            break;
        }
    }
    while(sum)
    {
        ++a[last];
        --sum;
        if(!sum)break;
        for(int i = last; i >= 2; --i)
        {
            --sum;
            ++a[i];
            if(!sum)break;
        }
    }
    int ans = 1;
    for(int i = 2; i <= last; ++i)ans *= a[i];
    cout << ans << endl;
    return;
}
int main()
{
    // freopen("input.txt", "r", stdin);
    // freopen("output.txt", "w", stdout);
    while(~scanf("%d", &n))
        solve();
    return 0;
}

テスト結果

intut:
10

output:
30

再帰と分割統治戦略

公共問題の数

タイトル

算法实现题    众数问题

问题描述:

  给定含有n 个元素的多重集合S,每个元素在S 中出现的次数称为该元素的重数。多重集S 中重数最大的元素称为众数。
  
例如,S={1,2,2,2,3,5}。
多重集S 的众数是2,其重数为3。

编程任务:

  对于给定的由n 个自然数组成的多重集S,编程计算S 的众数及其重数。

数据输入:

  输入数据由文件名为input.txt 的文本文件提供。文件的第1 行多重集S 中元素个数n;接下来的n 行中,每行有一个自然数。

结果输出: 

  程序运行结束时,将计算结果输出到文件output.txt 中。输出文件有2 行,第1 行给出众数,第2 行是重数。

输入文件示例          输出文件示例
input.txt             output.txt 
6                      2 
1                      3 
2 
2 
2 
3 
5 

アルゴリズムの考え方

各番号の出現回数ソートバイナリサーチは、最大値を記録します。

実験手順

#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e5;
int a[maxn];
int ans, ansn;
int n;
void solve()
{
    scanf("%d", &n);
    for(int i = 1; i <= n; ++i)scanf("%d", &a[i]);
    int l, r;
    l = r = 1;
    int t;
    sort(a + 1, a + 1 + n);
    ans = ansn = 0;
    for(int i = 1; i <= n; ++i)
    {
        l = lower_bound(a + 1, a + 1 + n, a[i]) - a - 1;
        r = upper_bound(a + 1, a + 1 + n, a[i]) - a - 1;
        t = r - l;
        if(t >= ansn)
        {
            ans = a[i];
            ansn = t;
            i = r;
        }
    }
    printf("%d\n%d\n", ans, ansn);
    return;
}
int main()
{
//    freopen("input.txt", "r", stdin);
//    freopen("output.txt", "w", stdout);

    solve();
    return 0;
}

テスト結果

input: 
6                      
1                      
2 
2 
2 
3 
5 

output:
2
3

整数素因数分解問題

タイトル

算法实现题    整数因子分解问题

问题描述:

 大于1 的正整数n 可以分解为:n=x1*x2*…*xm。
例如,当n=12 时,共有8 种不同的分解式:
12=12;
12=6*2;
12=4*3;
12=3*4;
12=3*2*2;
12=2*6;
12=2*3*2;
12=2*2*3 。

编程任务:

  对于给定的正整数n,编程计算n 共有多少种不同的分解式。

数据输入:

  由文件input.txt 给出输入数据。第一行有1 个正整数n (1≤n≤2000000000)。

结果输出: 

将计算出的不同的分解式数输出到文件output.txt 。

输入文件示例          输出文件示例
input.txt            output.txt 
 12                      8 

アルゴリズムの考え方

暴力を再帰的に型に起因するすべての可能な分解を見つけるために、あなたが数えることができます。(1E7は、1Sを超える可能性がより大きく、いくつかの整数のためのこのようなアプローチ)

実験手順

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
ll ans, n;
void solve(ll x)
{
    if(x == 1)
        ++ans;
    else
        for(int i = 2; i <= x; ++i)
            if(!(x % i))
                solve(x / i);
}
int main()
{
    freopen("input.txt", "r", stdin);
    freopen("output.txt", "w", stdout);

    while(cin >> n)
    {
        ans = 0;
        solve(n);
        cout << ans << endl;
    }
    return 0;
}

テスト結果

intput:
12
100
233
123456
10000000

output:
8
26
1
2496
3112896

おすすめ

転載: www.cnblogs.com/31415926535x/p/10963938.html