<01读书回忆录

来源:互联网 发布:矩阵乘法怎么算 编辑:程序博客网 时间:2024/05/22 10:38

从入门到上天

♥ACM篇♥

读后感<啊哈!算法>  点这里有惊喜.

输了你赢了世界又如何

!小姐姐图镇楼!啊哈!算法


※PS※
  1. 用到什么头文件用什么,不向复杂头文件低头
  2. 能用C++的输入输出就尽量用
  3. 如下一条
  4. 暂时不知道写啥。。。


A.简单排序

&book数组用法

0~1000的整数排序,用桶标记每个数出现次数,我们以后叫它布克先生(麻烦他帮助我们标记嘤嘤),book[t]
Input:输入一个正整数表示接下来有几个数
Output:按从大到小的顺序输出这几个数
Input:
10 8 100 50 22 15 6 1 1000 999 0
Output:1000 999 100 50 22 15 8 6 1 0

#include<iostream>#include<cstring>using namespace std;const int N = 1000;int main(){    int book[N + 1], i , j , t , n;    memset(book , 0 , sizeof(book));    cin>>n;    for(i = 0 ; i < n ; i++ ){        cin>>t;        book[t]++;    }    for(i = N ;i >= 0 ; i-- )        for(j = 1 ; j <= book[i] ; j++)        cout<<i<<" ";    return 0;}

我们来看布克先森的另一个例子,偶第一次用它过了的一个简单题

Description
有n个人比赛跳远。每个人跳3次,这个人的成绩就是三次距离里面的最大值。给出每个人三次跳的距离,问最终每个人的排名是多少。
Input
输入文件的第一行有一个整数T (1≤T≤100),表示测试数据的组数。对于每组测试数据:第一行包括一个整数n (2≤n≤3), 表示人数. 接下来n行, 每行包含三个整数ai,bi,ci (1≤ai,bi,ci,≤300), 表示第i个人每次的跳的距离。输入数据保证每个人的>成绩互不相同。
Output
对于每组数据,输出一行包含n个整数,用一个空格隔开。第i个数表示第i个人的最终名次。
Input
2
3
10 10 10
10 20 30
10 10 20
2
3 4 1
1 2 1
Output
3 1 2
1 2

#include<iostream>#include<algorithm>#include<cstring>using namespace std;int main(){    int a , b , c , t , n , score[4] , i , j , order[4];    cin>>t;    while(t--){        cin>>n;        for(i = 1 ; i <= n ; i++ ){            cin>>a>>b>>c;            score[i] = max(max(a , b) , c);        }        memset(order , 0 , sizeof(order));        for(i = 1 ; i <= n ; i++){            for(j = 1 ; j <=n ; j++ )                if(score[i] < score[j])                    order[i]++;        }        for( i = 1 ; i < n ; i++ ) cout<<order[i] + 1<<" ";        cout<<order[n] + 1<<endl;}    return 0;}

兴奋(当时是小白。。。^,^)的我又带着布克先森的智慧做了一道类似的题
□□□ + □□ = □□□ 将数字1~9分别填入□中,每个数字只能用一个,如173 + 286 = 459 就是一个合理的组合,请问有多少种这种合理的组合(173 + 286 = 459 与 286 + 173 = 459 是同一种)

#include<iostream>using namespace std;int main() {    int a[10] , i ,total = 0, book[10] , sum;    for(a[1] = 1 ; a[1] <=9 ; a[1]++ )        for(a[2] = 1 ; a[2] <=9 ; a[2]++ )            for(a[3] = 1 ; a[3] <=9 ; a[3]++ )                for(a[4] = 1 ; a[4] <=9 ; a[4]++ )                    for(a[5] = 1 ; a[5] <=9 ; a[5]++ )                        for(a[6] = 1 ; a[6] <=9 ; a[6]++ )                            for(a[7] = 1 ; a[7] <=9 ; a[7]++ )                                for(a[8] = 1 ; a[8] <=9 ; a[8]++ )                                    for(a[9] = 1 ; a[9] <=9 ; a[9]++ ){                                        for(i = 1 ; i <= 9 ; i++ ) book[i] = 0;                                        for(i = 1 ; i <= 9 ; i++ ) book[a[i]] = 1;                                        sum = 0;                                        for(i = 1 ; i <= 9 ; i++ ) sum += book[i];                                        if(sum == 9 && a[1] * 100 + a[2] * 10 + a[3] + a[1] * 100 + a[2] * 10 + a[3] + a[4] * 100 + a[5] * 10 + a[6] == a[7] * 100 + a[8] * 10 + a[9]){                                            total++;                                            cout<<a[1]<<a[2]<<a[3]<<"+"<<a[4]<<a[5]<<a[6]<<"="<<a[7]<<a[8]<<a[9]<<endl;                                        }    }    cout<<total / 2<<endl;    return 0;}

直到看到神奇的炸弹人才发现自己的做法简直是密集症恐惧者的地狱,于是果断思维进阶! (^.^) !


新生赛找字符串提也是book


&二分

Description
有n(n<=100)个整数,已经按照从小到大顺序排列好,另外给一个整数x,请将该数插入到序列中,使新的序列仍然有序。
Input
输入数据包含多个测试实例,每组数据由两行组成,第一行是n和m,第二行是已经有序的n个数的数列。n和m同时为0表示输入数据的结束,本行不做处理。
Output
对于每个测试实例,输出插入新的元素后的数列。
Input
3 3
1 2 4
0 0
Output
1 2 3 4

#include<iostream>#include<algorithm>using namespace std;const int N = 100 + 5;int main(){    int a[N], i , n , m , Begin , End , Half;    while(cin>>n>>m){        if(n == 0 && m != 0) cout<<m<<endl;        else if(n == 0 && m == 0) break;        else{            for(i = 0 ; i < n ; i++ ) cin>>a[i];            Begin = 0;            End = n - 1;            Half = 0;            while(Begin < End){                Half = ( Begin + End )/2;                if(a[Half] == m) break;                else if(m > a[Half]) Begin = ++Half;                else if(m < a[Half]) End = --Half;            }            if(m > a[Half]) Half++;        }        for(i = 0 ; i < Half ; i++ ){            if(i == 0) cout<<a[i];            else cout<<" "<<a[i];        }        if(i == 0)cout<<m;        else cout<<" "<<m;        for(i = Half ; i < n ; i++ ) cout<<" "<<a[i];        cout<<endl;    }    return 0;}

&双指针遍历

Problem Description
ZJH因为比赛原因,学习时间有所不足,所以很担心会挂科,甚至补考都不过,所以,是时候考虑一下应该优先学习那些科目。假定所有科目都用值Ai(i=0,1,2…)表示,我们称为“DB值”共有N个科目。毫无疑问,《c语言》肯定是应该排在Ai值最大的科目,现在他想知道下一个最应该考虑学习的科目的“DB值”是多少。
Input
输入包含多组数据。
输入第一行为N,表示有N(1< N<=100)个科目。
接下来一行有N个输入,表示N个科目的定值,其中包含了《c语言》。
Output
对每一组数组输出一行,包含下一个最应该考虑学习的科目的“DB值”。
2<=N<=100,每个整数的绝对值不超过10000.
SampleInput
5
8 9 12 33 2
3
1 3 3
SampleOutput
12
3

#include<iostream>#include<cstring>const int N = 100 + 5;using namespace std;int main(){    int i , n , score[N] , Max , Second ;    while(cin>>n){        memset(score , 0 , sizeof(score));        Max = -1, Second = -1;        for(i = 0 ; i < n ; i++ ){                cin>>score[i];        }        for(i = 0 ; i < n ; i++ ){            if(score[i] > Max){                Second = Max;                Max = score[i];            }            else{                if(score[i] > Second)                    Second = score[i];            }        }        cout<<Second<<endl;    }    return 0;}

&前缀和数组sum[i]

标号12345
13690
2 5表示从2到5的和
预处理


&求质数——欧拉筛法(又叫线性筛法,,,数学家果然惹不起)

额。。。大概是这样打表的,规定每个合数只用最小的一个质因数去筛选
时间复杂度为O (n)

#include<iostream>#include<cstring>using namespace std;const int MAXN = 100000000;const int MAXL = 100000000;int prime[MAXN];bool check[MAXL];int main(){    int i , j , n , count;    while (cin>>n){        memset(check, 0, sizeof(check));        count = 0;        for (i = 2; i <= n; i++){            if (!check[i])                 prime[count++] = i;            for (j = 0; j < count; j++){                if (i*prime[j] > MAXL) break; // 过大的时候跳出                check[i*prime[j]] = 1;                if ((i%prime[j]) == 0) break;// 如果i是一个合数,而且i % prime[j] == 0            }        }        for (i = 0; i < count; i++) cout<<prime[i]<<endl;    }    return 0;}

求区间[ a , b ]之间质数的个数。。。额需要复查

# include <cstdio># include <cstring># include <cctype># include <cmath># include <cstdlib># include <climits># include <iostream># include <iomanip># include <set># include <map># include <vector># include <stack># include <queue># include <algorithm>using namespace std;# ifdef ONLINE_JUDGEstruct QuickIO{    QuickIO(){const int SZ = 1<<20;        setvbuf(stdin ,new char[SZ],_IOFBF,SZ);        setvbuf(stdout,new char[SZ],_IOFBF,SZ);    }               //*From programcaicai*//}QIO;# endifconst int debug = 1;const int size  = 1000000 + 10;const int INF = INT_MAX>>1;typedef long long ll;int MAXNUM = size;bool *isprime;int *prime,prim_len = 0;void PrimerTable(int maxn){    isprime = new bool[maxn];    prime = new int[maxn];    fill(isprime,isprime+maxn,true);    isprime[0] = isprime[1] = false;    for (int i=2;i<maxn;i++){        if (isprime[i])            prime[prim_len++] = i;        for (int j=0;j<prim_len&&prime[j]*i<maxn;j++){            isprime[prime[j]*i] = false;            if (i%prime[j]==0)                break;        }    }}int ans[size];int main(){    std::ios::sync_with_stdio(false);cin.tie(0);    int i,j;    int a,b;    PrimerTable(MAXNUM);    for (i=2;i<MAXNUM;i++)        ans[i] = ans[i-1] + isprime[i];    while (cin >> a >> b){        cout << ans[b] - ans[a-1] << endl;    }    return 0;}

这里有一个666的应用,求欧拉函数

#include<cstdio>#include<cstring>#define MAXN 100005#define MAXL 1299710int prime[MAXN];int check[MAXL];int phi[MAXL];int tot = 0;phi[1] = 1;memset(check, 0, sizeof(check));for (int i = 2; i < MAXL; ++i){  if (!check[i])  {    prime[tot++] = i;    phi[i] = i - 1;  }  for (int j = 0; j < tot; ++j)  {    if (i * prime[j] > MAXL)    {      break;    }    check[i*prime[j]] = 1;    if (i % prime[j] == 0)    {      phi[i*prime[j]] = phi[i] * prime[j];      break;    }else    {      phi[i*prime[j]] = phi[i] * (prime[j]-1);    }  }}

哈哈,其实刚开始只懂得这个埃拉托斯特尼筛法(普通筛法。。。班尼特福迪听了想想敲人@_@)
时间复杂度为O (n log logn),<就是这跟 n 差的那么一丢丢,有的题就可能超时

埃拉托斯特尼筛法

看图很容易明白两种方法差距在哪

#include<iostream>#include<cstring>using namespace std;const int MAXN = 100000000;const int MAXL = 100000000;bool check[MAXN];int prime[MAXL];int main(){    int i , j , n , count;    while (cin>>n){        count = 0;        memset(check, 0, sizeof(check));        for (i = 2; i <= n; i++){            if (!check[i])  prime[count++] = i;            for (j = i + i; j <= n; j += i)                check[j] = 1;        }        for (int i = 0; i < count; i++) cout<<prime[i]<<endl;    }    return 0;}

说到这里不得不说的几个题。。。噗,我可能有强迫症
区间内完全平方数个数

#define _CRT_SECURE_NO_WARNINGS#include <stdio.h>#include <math.h>int main(int argc, char const *argv[]){    double numA = 0;    double numB = 0;    while(scanf("%lf %lf",&numA, &numB) != EOF )    {        int count = 0;        count = floor( sqrt(numB) ) - ceil( sqrt(numA) )+1;        printf("%d\n",count);    }   return 0;}

int gcd(int a, int b){    if (!b)        return a;    return gcd(b, a % b);}

快速幂

int quick(int a, int b){    int ans = 1;    while (b)    {        if (b & 1)            ans *= a;        a *= a;        b /= 2;    }    return ans;}

#include<iostream>#include<cmath>using namespace std;int Function(int n)  {    int count = 0;    for(count = 0 ; n ; ++count){        n &= (n - 1);    }    return count;}int main(){    int i , sum , a , n , t;    cin>>t;    while(t--){        cin>>n;        sum = 0;        for(i = pow(2 , n - 1) ; i < pow(2 , n) ; i++ ) {            a = Function(i);            sum += a;        }        cout<<sum<<endl;    }    return 0;}

B.暴力的枚举

&不知道该写啥


C.万能的搜索

&DFS



初级练级打小怪兽!!!    (T_T)百度云链接(密码:lj7p)

啊哈!算法