第二章:递归、分治(7.18)

递归

NC15173 The Biggest Water Problem
NC22164 更相减损术
NC208813 求逆序数

都是最基础的

NC207028 第k小数

记得读入优化(不然会T)

直接sort即可,但是可以通过这道题了解一下sort思想是什么

保证区间[l,mid]中的数都比[mid+1,r]中的小,再不停递归下去知道排序结束

#include<bits/stdc++.h>
#define LL long long
using namespace std;
int a[5000003];
int read()
{
    int f=1,x=0;char s=getchar();
    while(s<'0'||s>'9'){if(s=='-')f=-1;s=getchar();}
    while(s>='0'&&s<='9'){x=x*10+s-'0';s=getchar();}
    return x*f;
}
int find(int l,int r,int k)
{
    if(l==r)return a[l];
    int i=l,j=r;
    int mid=(l+r)>>1;
    int x=a[mid];
    while(i<=j)
    {
        while(a[j]>x)j--;
        while(a[i]<x)i++;
        if(i<=j)
        {
            swap(a[i],a[j]);//交换达到排序作用 
            i++;j--;
        }
    }
    if(k<=j)return find(l,j,k);
    else if(k>=i)return find(i,r,k);
    else return a[k];
} 
int main()
{
    int T=read();
    while(T--)
    {
        int n=read(),k=read();
        for(int i=1;i<=n;++i)a[i]=read();
        printf("%d\n",find(1,n,k));
    }
}
第k小数

NC201605 Bits

汉诺塔问题

NC16692 [NOIP2001]求先序排列

已知中序后序求先序

 (牛客上有比较简洁的代码写法)

#include<bits/stdc++.h>
using namespace std; 
void tree(string s1,string s2)
{
    int len1=s1.size();     
    int len2=s2.size();
    if(len1>0)
    {     
        char ch=s2[len2-1];    //根节点 
        cout<<ch;    //每次递归输出根节点 
        int pos=s1.find(ch);    //在s1中找到ch出现的位置 
        //substr(start,len)
        tree(s1.substr(0,pos),s2.substr(0,pos));    //递归左子树 
        tree(s1.substr(pos+1),s2.substr(pos,len1-pos-1));    //递归右子树 
    }
}
int main() 
{
    string str1,str2;
    cin>>str1>>str2;//中序后序 
    tree(str1,str2);    //构建左子树 
    return 0;
}
求先序排列

已知先序后序求中序也是

分治

NC16660 [NOIP2004]FBI树

注意字符串怎么打会比较简洁

#include<bits/stdc++.h>
using namespace std;
int n; 
char s[1300];
char FBI(string s)
{
    if(s.length()>1)
    {
        printf("%c",FBI(s.substr(0,s.length()/2)));
        printf("%c",FBI(s.substr(s.length()/2,s.length()/2)));
        
    }
    if (s==string(s.length(),'0')) return 'B';//all 0
    if (s==string(s.length(),'1')) return 'I';//all 1
    return 'F';
    
}
int main() 
{
    scanf("%d",&n);n=pow(2,n);
    scanf("%s",s);
    printf("%c",FBI(s));
}
FBI树

NC50999 表达式计算4

据说表达式计算用递归最不易出错

判断优先级和括号

#include<bits/stdc++.h>
using namespace std;
char s[40];
int number(int l,int r)
{
    int ans=0;
    for(int i=l;i<=r;++i)
      ans=ans*10+s[i]-'0';
    return ans;  
}
int work(int l,int r)
{
    int cnt=0;
    int add=-1,power=-1,mul=-1;
    for(int i=l;i<=r;++i)
    {
        if(s[i]=='(')cnt++;
        else if(s[i]==')')cnt--;//cnt记录括号 
        else if(!cnt)
        {
            
            switch(s[i])
            {
                case '+':
                case '-':
                    add=i;
                case '*':
                case '/':
                    mul=i;
                case '^':
                    power=i;
            }
        }
    }
    if(cnt>0&&s[l]=='(')//多余括号 
      return work(l+1,r);
    else if(cnt<0&&s[r]==')')
      return work(l,r-1);
    else if(!cnt&&add==-1&&mul==-1&&power==-1)
    {
        if(s[l]=='('&&s[r]==')')return work(l+1,r-1);//剩下的在式子里面 
        return number(l,r);//只剩下数字 
    }
//    else return 0;
    if(add!=-1)
    {
        if(s[add]=='+')return work(l,add-1)+work(add+1,r);
        else return work(l,add-1)-work(add+1,r);
    }
    if(mul!=-1)
    {
        if(s[mul]=='*')return work(l,mul-1)*work(mul+1,r);
        else return work(l,mul-1)/work(mul+1,r);
    }
    if(power!=-1)return pow(work(l,power-1),work(power+1,r));
    
}
int main() 
{
    scanf("%s",s);
    printf("%d\n",work(0,strlen(s)-1));
}
表达式计算4

NC23046 华华教月月做数学

快速幂和龟速乘

#include<bits/stdc++.h>
#define LL long long
using namespace std;
LL gsc(LL a,LL b,LL p)
{
    LL ans=0;
    while(b)
    {
        if(b&1)ans=(ans+a)%p;
        a=a*2%p;
        b>>=1;
    }
    return ans;
}
LL ksm(LL a,LL b,LL p)
{
    LL ans=1;
    while(b)
    {
        if(b&1)ans=gsc(ans,a,p);
        a=gsc(a,a,p);
        b>>=1;
    }
    return ans;
}
int main() 
{
    int T;scanf("%d",&T);
    while(T--)
    {
        LL a,b,p;scanf("%lld%lld%lld",&a,&b,&p);
        printf("%lld\n",ksm(a,b,p));
    } 
}
华华教月月做数学题
posted @ 2022-07-20 16:47  yyys  阅读(18)  评论(0编辑  收藏  举报