2018蓝桥杯省赛准备

ACM代码整合

如果发现文章中有不正确的地方,欢迎联系本人,感谢指出问题的每个人

PS:本文一切代码均有C/C++编写,参与JAVA组的人可以理解思想了以后尝试改写

!!!特别提醒

1、注意程序最后应有返回值,且返回值为0

2、万能头文件可以使用(bits/stdc++.h),比赛中使用c++的方法是,记得开全局空间using namespace std;

3、熟悉STL用法,包括vector、set、map、pair等结构的用法,这会给你剩下许多时间

4、例如max_element、lower_bound函数的用法请熟悉

5、在不能保证自己的算法的绝对正确性的情况下,可以选择保住现有的分,而不去尝试难度较高且自己没有把握的方法

1、最小公倍数gcd

int gcd(int a,int b){
    return b == 0 ? a : gcd(b,a%b);
} 

2、最大公约数lcm

int gcd(int a,int b){
    return b == 0 ? a : gcd(b,a%b);
} 

int lcm(int a,int b){
    return a*b/gcd(a,b);
}

3、Fibonacci数列

采用记忆化搜索的写法,或者使用状态转移的方法推导

  • 记忆化搜索写法
int dp[1005];
int dfs(int n){
    if(n==1 || n==2){
        return 1;
    }
    if(dp[n] > 0){
        return dp[n];
    }else{
        dp[n] = dfs(n-1) + dfs(n-2);
        return dp[n];
    }   
}
  • 状态转移写法
int dp[1000];
dp[1] = 1;
dp[2] = 1;
for(int i=3;i<1000;i++){
  dp[i] = dp[i-1] + dp[i-2];
} 

4、memset初始化

  • memset在整形数组中推荐两种用法
int dp[1005];
memset(dp,0,sizeof(dp));//dp中的值全部置为了0
memset(dp,-1,sizeof(dp));//dp中的值全部置为了-1

有人问1,2,3其他的可行,当然是不行的,至于原因有兴趣想要知道的话,可以在网上了解

  • memset在char数组中
char str[1005];
memset(str,0,sizeof(str));

这样就是将char数组重置了,在多组输入的情况中,memset将会是一个非常高效的方法

5、fill初始化

int dp[100];
fill(dp,dp+10,5);

此时dp[0] -> dp[9]的值全部被置为了5

char str[100];
fill(str,str+10,'m');

此时str[0] -> str[9]的值全部被置为了m

以上两个例子相信大家一下子就对fill有所了解了吧,在实际运用中大家可以根据自己的需要使用fill和memset

6、ctype.h头文件

函数名称函数原型函数功能函数返回
isalphaint isalpha(char ch)检查ch是否是字母是字母返回非0(在vs2015中为2),否则返回 0
iscntrlint iscntrl(int ch)检查ch是否控制字符(其ASCII码在0和0x1F之间,数值为 0-31)是返回非0,否则返回 0
isdigitint isdigit(char ch)检查ch是否是数字(0-9)是返回非0,否则返回0
isgraphint isgraph(int ch)检查ch是否可显示字符(其ASCII码在0x21到0x7E之间),不包括空格是返回非0,否则返回0
islowerint islower(int ch)检查ch是否小写字母(a-z)是返回非0,否则返回0
isupperint isupper(int ch)检查ch是否是大写字母(A-Z)是返回非0,否则返回0
tolowerint tolower(int ch)将ch字符转换为小写字母返回ch所代表的字符的小写字母
toupperint toupper(int ch)将ch字符转换成大写字母与ch相应的大写字母
isalnumint isalnum(int ch)检查ch是否是字母或数字是字母或数字返回非0,否则返回0
isprintint isprint(int ch)检查ch是否是可打印字符(包括空格),其ASCII码在0x20到0x7E之间是返回非0,否则返回0
ispunctint ispunct(int ch)检查ch是否是标点字符(不包括空格),即除字母,数字和空格以外的所有可打印字符是返回非0,否则返回0
isspaceint isspace(int ch)检查ch是否是空格符和跳格符(控制字符)或换行符是返回非0,否则返回0
isxdigitint isxdigit(int ch)检查ch是否是一个16进制数学字符(即0-9,或A-F,或a-f)是返回非0,否则返回0
isasciiint isascii(int ch)测试参数是否是ASCII码0-127是返回非0,否则返回0

7、素数系列

  • 埃拉托斯特尼筛法,或者叫埃氏筛法
const int N = 100005;  
bool prime[N];  
void init(){  
    for(int i=2;i<N;i++) prime[i]=true;//先全部初始化为素数  
    for(int i=2;i*i<N;i++){  
        if(prime[i]){//如果i是质数  
            for(int j=i*i;j<N;j+=i){//从i的两倍开始的所有的倍数(i*i也行)  
                prime[j] = false;  
            }  
        }  
    }  
}  
  • 预处理每个数的所有质因数
const int N = 100000 + 5;  
vector<int > prime_factor[N];  
void init(){  
    for(int i = 2; i < N; i ++){  
        if(prime_factor[i].size() == 0){//如果i是质数   
            for(int j = i; j < N; j += i){  
                prime_factor[j].push_back(i);   
            }  
        }  
    }  
} 
  • 比如预处理每个数的所有因数
const int N = 100000 + 5;  
vector<int > factor[N];  
void init(){  
    for(int i = 2; i < N; i ++){  
        for(int j = i; j < N; j += i){  
            factor[j].push_back(i);  
        }  
    }  
}
  • 预处理每个数的质因数分解
const int N = 100000 + 5;  
vector<int > prime_factor[N];  
void init(){  
    int temp;  
    for(int i = 2; i < N; i ++){  
        if(prime_factor[i].size() == 0){  
            for(int j = i; j < N; j += i){  
                temp = j;  
                while(temp % i == 0){  
                    prime_factor[j].push_back(i);  
                    temp /= i;  
                }  
            }  
        }  
    }  
}

http://blog.csdn.net/laichilizi/article/details/79390020

质因数分解题目↑(输入两个整数a、b,每行输出一个数的分解,形如k=a1*a2*a3…(a1<=a2<=a3….)

#include<bits/stdc++.h>    
using namespace std;    
const int N = 100000 + 5;    
vector<int > prime_factor[N];    
void init(){    
    int temp;    
    for(int i = 2; i < N; i ++){    
        if(prime_factor[i].size() == 0){    
            for(int j = i; j < N; j += i){    
                temp = j;    
                while(temp % i == 0){    
                    prime_factor[j].push_back(i);    
                    temp /= i;    
                }    
            }    
        }    
    }    
}    
int main()  
{    
    init();   

    int a,b;  
    scanf("%d %d",&a,&b);  
    vector<int>::iterator it;  
    for(int i=a;i<=b;i++){  
        cout<<i<<"=";  
        for(it = prime_factor[i].begin(); it != prime_factor[i].end(); it++){  
            if(it != prime_factor[i].end()-1) cout << *it <<"*";  
            else cout<<*it<<endl;  
        }  

    }   
}  

8、BFS系列

http://blog.csdn.net/laichilizi/article/details/75024841

  • 马的移动↑,BFS入门题

http://blog.csdn.net/laichilizi/article/details/79383954

  • 学霸的迷宫↑,BFS+记录操作方向

9、DFS系列

http://blog.csdn.net/laichilizi/article/details/79388913

  • 正则问题↑,一个由x()|组成的正则表达式。输入长度不超过100,保证合法,求这个正则表达式能接受的最长字符串的长度

http://blog.csdn.net/laichilizi/article/details/78714582

  • POJ-2386,简单区域连通问题,↑

10、动态规划(01背包,完全背包)

  • 01背包(记忆化搜索)
#include<bits/stdc++.h>  
using namespace std;  
typedef long long ll;  

int n,W;  
int dp[105][10005];  
int w[105],v[105];  

int rec(int i,int j){  
    if(dp[i][j] >= 0){  
        return dp[i][j];  
    }  
    int res;  
    if(i == n){  
        res = 0;  
    }else if(j < w[i]){  
        res = rec(i + 1,j);  
    }else{  
        res = max(rec(i + 1,j),rec(i + 1,j - w[i])+v[i]);  
    }  

    return dp[i][j] = res;  
}  

int main()  
{  
    scanf("%d %d",&n,&W);  

    for(int i=0;i<n;i++){  
        scanf("%d %d",&w[i],&v[i]);   
    }  

    memset(dp,-1,sizeof(dp));  

    cout<<rec(0,W)<<endl;  


    return 0;  
}  
  • 01背包(二维DP)
#include<bits/stdc++.h>  
using namespace std;  
typedef long long ll;  

int n,W;  
int dp[105][10005];  
int w[105],v[105];  

int main()  
{  
    scanf("%d %d",&n,&W);  

    for(int i=0;i<n;i++){  
        scanf("%d %d",&w[i],&v[i]);   
    }  

    memset(dp,0,sizeof(dp));  

    for(int i=n-1;i>=0;i--){  
        for(int j=0;j<=W;j++){  
            if(j < w[i]){  
                dp[i][j] = dp[i + 1][j];  
            }else{  
                dp[i][j] = max(dp[i+1][j],dp[i+1][j-w[i]]+v[i]);  
            }  
        }  
    }  

    cout<<dp[0][W]<<endl;  

    return 0;  
}  
  • 01背包(一维最简化)
int dp[MAX_W +1];

void solve(){
    for(int i=0;i<n;i++){
        for(int j=W;j>=w[i];j--){
            dp[j] = max(dp[j],dp[j-w[i]]+v[i]);
        }
    }
    printf("%d\n",dp[W]);
}
  • 完全背包(一维最简化)
int dp[MAX_W +1];

void solve(){
    for(int i=0;i<n;i++){
        for(int j=w[i];j<=W;j--){
            dp[j] = max(dp[j],dp[j-w[i]]+v[i]);
        }
    }
    printf("%d\n",dp[W]);
}

11、并查集

int par[MAX_N];
int rank[MAX_N];

//初始化n个元素 
void init(int n){
    for(int i=0;i<n;i++){
        par[i] = i;
        rank[i] = 0;
    }
}

//查询树的根 
int find(int x){
    if(par[x] == x){
        return x;
    }else{
        return par[x] = find(par[x]);
    }
}

//合并x和y所属的集合 
void unite(int x,int y){
    x = find(x);
    y = find(y);
    if(x == y) return;
    if(rank[x] < rank[y]){
        par[x] = y;
    }else{
        par[y] = x;
        if(rank[x] == rank[y]) rank[x]++;
    }
}

//判断x和y是否属于同一个集合
bool same(int x,int y){
    return find(x) == find(y);
}

经典例题:hdu1232

#include<cstdio>
using namespace std;

int par[1005];
int rank[1005];

//初始化n个元素
void init(int n){
    for(int i=1;i<=n;i++){
        par[i] = i;
        rank[i] = 0;
    }
}

//查询树的根
int find(int x){
    if(par[x] == x){
        return x;
    }else{
        return par[x] = find(par[x]);
    }
}

//合并x和y所属的集合
void unite(int x,int y){
    x = find(x);
    y = find(y);
    if(x == y) return;
    if(rank[x] < rank[y]){
        par[x] = y;
    }else{
        par[y] = x;
        if(rank[x] == rank[y]) rank[x]++;
    }
}

//判断x和y是否属于同一个集合
bool same(int x,int y){
    return find(x) == find(y);
}

int main()
{
    int n,m;
    while(~scanf("%d%d",&n,&m)){
        if(n == 0) break;
        init(n);
        for(int i=0;i<m;i++){
            int x,y;
            scanf("%d%d",&x,&y);
            unite(x,y);
        }
        int ans = 0;
        for(int i=1;i<=n;i++){
            if(par[i] == i) ans ++;
        }
        printf("%d\n",ans-1);
    }

    return 0;
}

12、树状数组

int lowbit(int x){  
    return x&(-x);  
}  

void add(int x,int y){  
    while(x<=n){  
        c[x]+=y;  
        x+=lowbit(x);  
    }  
}  

//用于求序列中小于等于数字x的元素的个数
int sum(int x){  
    int ans=0;  
    while(x>0){  
        ans+=c[x];  
        x-=lowbit(x);  
    }       
    return ans;  
} 

http://blog.csdn.net/laichilizi/article/details/79450529

  • 求逆序数↑
#include<iostream>  
#include<cstdio>  
using namespace std;  
int n;  
int aa[100005];  
int c[100005];  
int a[100005];  
int lowbit(int x)  
{  
    return x&(-x);  
}  
void add(int x,int y)  
{  
    while(x<=n)  
    {  
        c[x]+=y;  
        x+=lowbit(x);  
    }  
}  
int sum(int x)  
{  
    int ans=0;  
    while(x>0)  
    {  
        ans+=c[x];  
        x-=lowbit(x);  
    }  

    return ans;  
}  

int main()  
{  
    scanf("%d",&n);  
    for(int i=0;i<n;i++)  
    {  
        scanf("%d",&a[i]);  
    //  aa[a[i]]=a[i];  
    }   long long aans=0;  
    for(int i = 0 ; i<n;i++)  
    {  
        add(a[i],1);  
        aans+=i-sum(a[i]-1);  
    //  cout << i;  
    //  cout << sum(a[i]-1)<<endl;;  
    }  

    printf("%lld\n",aans);  
    return 0;  
} 

13、快速幂 and 矩阵快速幂

  • 快速幂
typedef long long ll;
ll ksm(ll x,ll n,ll mod){
    ll res = 1;
    x = x % mod;
    while(x > 0){
        if(n & 1) res = res * x % mod;
        x = x * x % mod;
        n >>= 1;
    }
    return res;
}
  • 矩阵快速幂

http://blog.csdn.net/wust_zzwh/article/details/52058209

#include<bits/stdc++.h>  
using namespace std;  
typedef long long ll;  
const int MOD=10000;  
struct mat  
{  
    ll a[2][2];  
};  
mat mat_mul(mat x,mat y)  
{  
    mat res;  
    memset(res.a,0,sizeof(res.a));  
    for(int i=0;i<2;i++)  
        for(int j=0;j<2;j++)  
        for(int k=0;k<2;k++)  
        res.a[i][j]=(res.a[i][j]+x.a[i][k]*y.a[k][j])%MOD;  
    return res;  
}  
void mat_pow(int n)  
{  
    mat c,res;  
    c.a[0][0]=c.a[0][1]=c.a[1][0]=1;  
    c.a[1][1]=0;  
    memset(res.a,0,sizeof(res.a));  
    for(int i=0;i<2;i++) res.a[i][i]=1;  
    while(n)  
    {  
        if(n&1) res=mat_mul(res,c);  
        c=mat_mul(c,c);  
        n=n>>1;  
    }  
    printf("%I64d\n",res.a[0][1]);  
}  
int main()  
{  
    int n;  
    while(~scanf("%d",&n)&&n!=-1)  
    {  
        mat_pow(n);  
    }  
    return 0;  
}

14、最短路

http://blog.csdn.net/acm_1361677193/article/details/48211319

15、string

http://blog.csdn.net/tengfei461807914/article/details/52203202

16、二分搜索

二分模型

while(l < r-1){
        int mid = r + (l - r)>> 1;
        if() l = mid;
        else r = mid;
    }

http://blog.csdn.net/laichilizi/article/details/79388555

  • 分巧克力↑,经典二分题

17、字符串函数

  • 字符处理函数:ctype.h
int isdigit(int ch)  ;//是否为数字,即ch是否是0-9中的字符
int isxdigit(int ch) ;//是否为十六进制数字,即ch是否是0-9  a-z A-Z 中的字符
int isalpha(int ch)  ;//是否为字母
int isalnum(int ch)  ;//是否为字母或数字
int islower(int ch)  ;//是否为小写字母
int isupper(int ch)  ;//是否为大写字母
int tolower(int ch)  ;//转换为小写字母
int toupper(int ch)  ;//转换为大写字母
  • 字符串转换函数:stdlib.h

字符转换为数字:

double atof(char  *str) ; //将字符串str转换为double型数字
int    atoi (char  *str) ; //将字符串str转换为int 型数字
long   atol(char  *str) ; //将字符串str转换为long int 型数字

数字转换为字符:

//将int型数字digit按radix进制转换成字符串destStr
char * itoa (int digit, char *destStr, int radix) ;
//同理将long型数字转换成字符串
char * ltoa (long digit, char *destStr, int radix) ;
//同理将unsignedlong型数字转换成字符串
char * ultoa (long digit, char *destStr,int radix) ;

【以上库函数能够用于进制的转换】

类似函数还有:

double strtod(char *, char **) ;
long strtol(char *, char **, int) ;
unsigned long strtoul(char *, char **, int) ;
  • 字符串操作函数:string.h
char * strcpy (char *s1, char *s2) ; //将字符串s2拷贝到数组s1中。
char * strncpy(char *s1,char *s2) ; //将字符串s2的最多n个字符拷贝到数组s1中
char * strcat (char *s1, char * s2) ; //将字符串s2连接在字符串s1尾部
char * strncat(char *s1, char *s2, size_tn) ; //将字符串s2中最多n个字符连接在s1之后

【注意:以上操作都要求目标字符数组有足够的存储空间】

  • 符串比較函数:string.h
//比較字符串s1,s2.假设s1等于小于或大于s2。分别返回0。负值,正值
int strcmp(char *s1, char *s2 ) ;
int stricmp(char *s1, char *s2) ;//不区分大写和小写地比較两字符串
int strncmp(char *s1, char *s2, size_t n)  ;//比較两字符串的至多n个字符
  • 字符串查找函数:string.h
//在字符串str中查找字符ch第一次出现的位置,假设找到了,就返回str中ch的指针,否则返回NULL
char *strchr(char*str, int ch) ;
//查找字符串str中字符ch的最后一次出现的位置(即:从后往前查找)
char*strrchr(char *str, int ch) ;
//查找字符串str1中第一次出现字符串str2的位置
char *strstr(char*str1, char *str2) ;
//查找字符串str2中随意字符在字符串str1中首次出现的位置。
char*strpbrk(char *str1, char *str2)

其他函数:

char *strrev(char * ) ; //字符串逆序函数
size_t strlen(char * str) ;//測字符串str的长度

注意:

strncpy( ) , strncat( ) , strncmp( ) ,这些函数仅仅能对两个不同的字符串操作,不能对同一字符串的不同部分操作。假设须要这么做,能够使用内存函数。

若把目标字符串初始置空,strncat()能够完毕非常多功能的操作。能够替代strncpy( )的功能,还能够提取子串等。

18、set & multiset

19、map & multimap

20、queue & priority_queue

  • queue

queue入队,如例:q.push(x); 将x 接到队列的末端。

queue出队,如例:q.pop(); 弹出队列的第一个元素,注意,并不会返回被弹出元素的值。

访问queue队首元素,如例:q.front(),即最早被压入队列的元素。

访问queue队尾元素,如例:q.back(),即最后被压入队列的元素。

判断queue队列空,如例:q.empty(),当队列空时,返回true。

访问队列中的元素个数,如例:q.size()

  • priority_queue

empty() 如果优先队列为空,则返回真

pop() 删除第一个元素

push() 加入一个元素

size() 返回优先队列中拥有的元素的个数

top() 返回优先队列中有最高优先级的元素

21、stack

empty() 堆栈为空则返回真

pop() 移除栈顶元素

push() 在栈顶增加元素

size() 返回栈中元素数目

top() 返回栈顶元素

22、vector

http://blog.csdn.net/duan19920101/article/details/50617190/

23、贪心算法

http://blog.csdn.net/qq_32400847/article/details/51336300

24、数制转换

http://blog.csdn.net/laichilizi/article/details/79381732

25、LCS

只计算LCS的数目

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;

char a[1005],b[1005],ans[1005];
int dp[1005][1005];
int main()
{
    //freopen("input.txt","r",stdin);

    scanf("%s %s",a+1,b+1);
    int n = strlen(a+1);
    int m = strlen(b+1);
    memset(dp,0,sizeof(dp));

    for(int i=1;i<=n;i++){
        for(int j=1;j<=m;j++){
            if(a[i] == b[j]){
                dp[i][j] = dp[i-1][j-1] + 1;
            }else{
                dp[i][j] = max(dp[i-1][j],dp[i][j-1]);
            }
        }
    }

    cout<<dp[n][m]<<endl;

    return 0;
}

除了LCS的数目,还输出对应的子串

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;

char a[1005],b[1005],ans[1005];
int dp[1005][1005];
int main()
{
    //freopen("input.txt","r",stdin);

    scanf("%s %s",a+1,b+1);
    int n = strlen(a+1);
    int m = strlen(b+1);
    memset(dp,0,sizeof(dp));

    for(int i=1;i<=n;i++){
        for(int j=1;j<=m;j++){
            if(a[i] == b[j]){
                dp[i][j] = dp[i-1][j-1] + 1;
            }else{
                dp[i][j] = max(dp[i-1][j],dp[i][j-1]);
            }
        }
    }
    int cur = 0;
    for(int i=n,j=m;dp[i][j];--i,--j){
        while(dp[i][j] == dp[i-1][j]) --i;
        while(dp[i][j] == dp[i][j-1]) --j;
        ans[cur++] = a[i];
    }

    reverse(ans,ans+cur);
    //ans[cur] = '\0';
    printf("%s\n",ans);

    return 0;
}

26、LIS

#include<bits/stdc++.h>  
using namespace std;  
#define INF 0x3f3f3f3f  
typedef long long ll;  

int dp[105];  
int a[105];  

int main()  
{  
    int n;  
    scanf("%d",&n);  
    for(int i=0;i<n;i++) scanf("%d",&a[i]);  

    int res = 0;  
    for(int i=0;i<n;i++){  
        dp[i] = 1;  
        for(int j=0;j<i;j++){  
            if(a[j] < a[i]){ //如果是包括相等,就改为<=   
                dp[i] = max(dp[i],dp[j]+1);  
            }  
        }  
        res = max(res,dp[i]);   
    }  
    cout<<res<<endl;  

    return 0;  
}

27、最大字段和

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;

ll dp[50005];

ll solve(int n,ll *dp){
    ll ans = 0,b = 0;
    for(int i=0;i<n;i++){
        if(b>=0) b+=dp[i];
        else b = dp[i];
        if(b>ans) ans = b;
    }
    return ans;
}

int main(){
    //freopen("input.txt","r",stdin);
    int n;
    scanf("%d",&n);
    memset(dp,0,sizeof(dp));

    for(int i=0;i<n;i++) scanf("%lld",&dp[i]);
    ll p = solve(n,dp);
    cout<<p<<endl;

    return 0;
}

28、循环数组最大字段和

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;

ll dp[50005];

ll solve(int n,ll *dp){
    ll ans = 0,b = 0;
    for(int i=0;i<n;i++){
        if(b>=0) b+=dp[i];
        else b = dp[i];
        if(b>ans) ans = b;
    }
    return ans;
}

int main(){
    freopen("input.txt","r",stdin);
    int n,sum = 0;
    scanf("%d",&n);
    memset(dp,0,sizeof(dp));

    for(int i=0;i<n;i++){
        scanf("%lld",&dp[i]);
        sum += dp[i];
    }
    ll ans1 = solve(n,dp);

    for(int i=0;i<n;i++) dp[i] = -dp[i];
    ll ans2 = solve(n,dp);
    ll ans = max(ans1,sum+ans2);

    cout<<ans<<endl;

    return 0;
}

29、最小正字段和

#include<iostream>  
#include<cstdio>  
#include<cstring>  
#include<algorithm>  
using namespace std;  
typedef long long LL;  
#define INF 0x3f3f3f3f;

struct node{  
    LL a;  
    int id_mi;  
    int id_ma;  
};  
bool operator <(node a,node b){  
    return a.a<b.a;  
}  
node dp[50010];  
int main(){  
    int n,a,i,j;  
    scanf("%d",&n);  
    LL ans=0;  
    dp[0].a=0;  
    dp[0].id_mi=0;  
    dp[0].id_ma=0;  
    for(i=1;i<=n;i++){  
        scanf("%lld",&dp[i].a);  
        dp[i].a+=dp[i-1].a;  
        dp[i].id_mi=i;  
        dp[i].id_ma=i;  

    }  
    sort(dp,dp+1+n);  
    j=0;  
    for(i=1;i<=n;i++)  
    {  
        if(dp[i].a==dp[j].a){  
            dp[j].id_mi=max(dp[j].id_mi,dp[i].id_mi);  
            dp[j].id_ma=min(dp[j].id_ma,dp[i].id_ma);  
        }  
        else dp[++j]=dp[i];  
    }  
    for(i=0;i<j;i++){  
        if(dp[i].id_mi<dp[i+1].id_ma&&dp[i+1].a-dp[i].a>0&&(ans==0||ans>dp[i+1].a-dp[i].a)){  
            ans=dp[i+1].a-dp[i].a;  
        }  
    }  
    cout<<ans<<endl;  
    return 0;  
}  

30、大数运算

http://blog.csdn.net/tt2767/article/details/45420067

31、Trie

const int MAX_N = 10000;  // Trie 树上的最大结点数
const int MAX_C = 26;  // 每个结点的子结点个数上限
struct Trie {
    int *ch[MAX_N];  // ch 保存了每个结点的 26 个可能的子结点编号,26 对应着 26 种小写字母,也就是说,插入的字符串全部由小写字母组成。初始全部为 -1
    int tot;  // 总结点个数(不含根结点),初始为 0
    int cnt[MAX_N];  // 以当前结点为终端结点的 Trie 树中的字符串个数

    void init() {  // 初始化 Trie 树,根结点编号始终为 0
        tot = 0;
        memset(cnt, 0, sizeof(cnt));
        memset(ch, 0, sizeof(ch));  // 将 ch 中的元素初始化为 NULL
    }

    void insert(char *str) {
        int p = 0;  // 从根结点(0)出发
        for (int i = 0; str[i]; ++i) {
            if (ch[p] == NULL) {
                ch[p] = new int[MAX_C];  // 只有 p 当包含子结点的时候才去开辟 ch[p] 的空间
                memset(ch[p], -1, sizeof(int) * MAX_C);  // 初始化为 -1
            }
            if (ch[p][str[i] - 'a'] == -1) {  // 该子结点不存在
                ch[p][str[i] - 'a'] = ++tot;  // 新增结点
            } 
            p = ch[p][str[i] - 'a'];  // 在 Trie 树上继续插入字符串 str
        }
        cnt[p]++;
    }

    int find(char *str) {  // 返回字符串 str 的出现次数
        int p = 0;
        for (int i = 0; str[i]; ++i) {
            if (ch[p][str[i] - 'a'] == -1) {
                return 0;
            }
            p = ch[p][str[i] - 'a'];
        }
        return cnt[p];
    }
};
  • 14
    点赞
  • 75
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值