zoukankan      html  css  js  c++  java
  • 第十二关——2012提高组真题

    17:39:56 我只见他对我笑过两次,一次生离,一次死别。——南派三叔《盗墓笔记》

    总结:2012提高组真题类型

    • 第一题 Vigenère 密码:模拟暴力
    • 第二题 国王游戏:贪心+高精度
    • 第三题 开车旅行:倍增
    • 第四题 同余方程:扩展欧几里得
    • 第五题 借教室:线段树/前缀数组

    第一题 Vigenère 密码

    要考虑的就是密钥k的长度问题,如果k的长度不够,我们需要把k不断的从第一个开始往后拼,直到拼到密文的长度,便于我们进行处理;

    注意ASCLL码的转换,大小写中相差多少

    #include<bits/stdc++.h>
    using namespace std;
    char aa[10001],bb[10001],ans[10001];
    bool check(int x)
    {
        if(x>='a' && x<='z')return true;
        return false;
    }
    int main()
    {
        string t,k;
        cin>>k>>t;
        int lk=k.length(),lt=t.length();
        for(int i=0;i<lk;i++)
        aa[i]=k[i];
        for(int i=0;i<lt;i++)
        bb[i]=t[i];
        for(int i=0,j=0;i<lt;i++,j++)
        {
            if(j==lk)j=0;
            if(check(bb[i]))
            {
                if(!check(aa[j]))aa[j]+='a'-'A';
                ans[i]=bb[i]-aa[j]+'a';
                if(ans[i]<'a')ans[i]+=26;
            }
            if(!check(t[i]))
            {
                if(check(aa[j]))aa[j]+='A'-'a';
                ans[i]=bb[i]-aa[j]+'A';
                if(ans[i]<'A')ans[i]+=26;
            }
        }    
        for(int i=0;i<lt;i++)
        cout<<ans[i]; 
        return 0;
    }

    第二题 国王游戏

    这道题使用的是贪心算法加高精度(重要的还是要熟悉高精度吧)、

    #include<bits/stdc++.h>
    #define ll long long
    using namespace std;
    ll n;
    struct sby{
        ll a,b,ab;
    }h[10100];
    ll now[10100],ans[10100],minn[10100];
    bool cmp(sby a,sby b){
        return a.ab<b.ab;
    }
    void c(ll x){
        for(register ll i=1;i<=now[0];++i)
            now[i]*=x;
        for(register ll i=1;i<=now[0];++i){
            now[i+1]+=now[i]/10;
            now[i]%=10;
            if(i==now[0]&&now[i+1]!=0) now[0]++;
        }
    }
    void ss(ll x){
        memset(minn,0,sizeof(minn));
        ll q=0;
        for(register ll i=now[0];i>=1;--i){
            q=q*10+now[i];
            minn[i]=q/x;
            if(minn[0]==0&&minn[i]!=0) minn[0]=i;
            q%=x;
        }
        for(register ll i=1;i<=minn[0];++i){
            minn[i+1]+=minn[i]/10;
            minn[i]%=10;
            if(i==minn[0]&&minn[i+1]!=0) minn[0]++;
        }
    }
    bool com(){
        if(minn[0]>ans[0]) return 1;
        if(ans[0]>minn[0]) return 0;
        for(register ll i=ans[0];i>=1;--i){
            if(minn[i]>ans[i]) return 1;
            if(minn[i]<ans[i]) return 0;
        }
        return 0;
    }
    void xz(){
        for(register ll i=0;i<=minn[0];++i)
            ans[i]=minn[i];
    }
    int main(){
        scanf("%d",&n);
        for(register ll i=0;i<=n;++i){
            scanf("%d%d",&h[i].a,&h[i].b);
            h[i].ab=h[i].a*h[i].b;
        }
        sort(h+1,h+1+n,cmp);
        now[1]=1;
        now[0]=1;
        for(register ll i=1;i<=n;++i){
            c(h[i-1].a);
            ss(h[i].b);
            if(com())
                xz();
        }
        for(register ll i=ans[0];i>=1;--i)
        printf("%d",ans[i]);
        return 0;
    }

    第三题 开车旅行

    s.insert(x);//插入x
    s.lower_bound(x);//查找**大于等于**x的最小元素,返回迭代器
    s.upper_bound(x);//查找**大于**x的最小元素,返回迭代器

    由于本题木有修改操作,并且到每个点的下一个点的位置确定,很容易想到倍增来优化,同时由于本题的需要,除f[i][j]外,在定义两个数组sa[i][j]和sb[i][j]],分别表示第i个点走2^j天A所走的路程和B所走的路程。

    #include<bits/stdc++.h>
    #define INF 50000000000
    #define ll long long
    #define N 100005
    using namespace std;
    struct sby{
        ll h,xz;
    }t[5];
    set<ll>s;
    map<ll,ll>mp;
    ll n,h[N],a[N],b[N],fa[N],fb[N],sa[N][25],sb[N][25],f[N][25];
    bool cmp(sby aa,sby bb){
        return (aa.xz==bb.xz?aa.h<bb.h:aa.xz<bb.xz);
    }
    void st(){
        for(ll i=n;i>=1;i--){
            s.insert(h[i]);
            t[1].h=*--s.lower_bound(h[i]);
            t[3].h=*--s.lower_bound(t[1].h); 
            t[2].h=*s.upper_bound(h[i]); 
            t[4].h=*s.upper_bound(t[2].h);
            for(ll j=1;j<=4;j++)t[j].xz=abs(t[j].h-h[i]);
            sort(t+1,t+5,cmp);
            a[i]=t[2].xz;fa[i]=mp[t[2].h];
            b[i]=t[1].xz;fb[i]=mp[t[1].h];
            if(fa[i])sa[i][0]=a[i],f[i][0]=fa[i];
            if(fb[fa[i]])sa[i][1]=a[i],sb[i][1]=b[fa[i]],f[i][1]=fb[fa[i]];
            for(ll j=2;j<=16;j++)
                if(f[f[i][j-1]][j-1]){
                    sa[i][j]=sa[i][j-1]+sa[f[i][j-1]][j-1];
                    sb[i][j]=sb[i][j-1]+sb[f[i][j-1]][j-1];
                    f[i][j]=f[f[i][j-1]][j-1];
                }
                else break;
        }
    }
    double ask1(ll x,ll p){
        ll s1=0,s2=0;
        for(ll i=16;i>=0;i--){
            if(f[x][i]&&s1+s2+sa[x][i]+sb[x][i]<=p){
                s1+=sa[x][i];
                s2+=sb[x][i];
                x=f[x][i];
            }
        }
        return (s2==0?INF:(double)s1/(double)s2);
    }
    void ask2(ll x,ll p){
        ll s1=0,s2=0;
        for(ll i=16;i>=0;i--){
            if(f[x][i]&&s1+s2+sa[x][i]+sb[x][i]<=p){
                s1+=sa[x][i];
                s2+=sb[x][i];
                x=f[x][i];
            }
        }
        if(fa[x]&&s1+s2+sa[x][0]<=p)s1+=sa[x][0];
        printf("%lld %lld
    ",s1,s2);
    }
    void solve(){ 
        double minn=INF;
        ll bj,x0;
        scanf("%lld",&x0);
        for(ll i=1;i<=n;i++){
            double op=ask1(i,x0);
            if(op<minn)minn=op,bj=i;
        }
        printf("%lld
    ",bj);
        ll m,s0;
        scanf("%lld",&m);
        while(m--){
            scanf("%lld%lld",&s0,&x0);
            ask2(s0,x0);
        }
    }
    int main(){
        s.insert(INF);s.insert(INF-1);s.insert(-INF);s.insert(-INF+1);
        scanf("%lld",&n);
        for(ll i=1;i<=n;i++)scanf("%lld",&h[i]),mp[h[i]]=i;
        st();
        solve();
        return 0;
    }

     第四题 同余方程

    这道题要用扩展欧几里得来做,是一道在数论中还比较简单的题,不过还是需要推一下

    注意:方程 ax + by = m有解的必要条件是 mod gcd(a,b)=0

    #include<bits/stdc++.h>
    #define ll long long 
    using namespace std;
    ll a,b,x,y;
    ll sby(ll a,ll b,ll &x,ll &y)
    {
        if(!b){x=1;y=0;return a;}
        ll d=sby(b,a%b,x,y);
        ll z=x;x=y;y=z-y*(a/b);
        return d;
    }
    int main()
    {
        cin>>a>>b;
        sby(a,b,x,y);
        cout<<(x%b+b)%b<<endl;
        return 0;
    }

    第五题 借教室

    这道题我用的是线段树的做法,需要用到线段树的区间修改(详细看笔记)。还算是一个比较模板的线段树

    临界条件是t[1].w-t[1].ti<0,如果满足,则证明教师数目不够,需要通知,则输出i即可
    #include<bits/stdc++.h>
    using namespace std;
    const int N=1000006;
    struct sby{
        int l,r,w,ti;
    }t[N<<2];
    int l,r,s,a[N],n,m;
    int read(){
        int s = 0, w = 1; char ch = getchar();
        while(ch < '0' || ch > '9')   { if(ch == '-') w = -1; ch = getchar(); }
        while(ch >= '0' && ch <= '9') { s = (s << 3) + (s << 1) + (ch ^ 48); ch = getchar(); }
        return s * w;
    }
    void build(int l,int r,int k)
    {
        t[k].l=l;t[k].r=r;
        if(l==r){
            t[k].w=a[l];
            return;
        }
        int mid=(l+r)/2;
        build(l,mid,k*2);
        build(mid+1,r,k*2+1);
        t[k].w=min(t[k*2].w,t[k*2+1].w);
    }
    void ss(int k){
        int o;
        o=min(t[k*2].w-t[k*2].ti,t[k*2+1].w-t[k*2+1].ti);
        t[k].w=min(t[k].w,o);
    }
    void change(int l,int r,int k,int mun)
    {
        if(t[k].l==l&&t[k].r==r){
            t[k].ti+=mun;
            return ;
        }
        int mid=(t[k].l+t[k].r)/2;
        if(r<=mid) 
        change(l,r,k*2,mun);
        else if(l>mid) 
        change(l,r,k*2+1,mun);
        else 
        change(l,mid,k*2,mun),change(mid+1,r,k*2+1,mun);
        ss(k);
    }
    int main()
    {
        n=read();m=read();
        for(int i=1;i<=n;i++)
        a[i]=read();
        build(1,n,1);
        for(int i=1;i<=m;i++)
        {
            s=read();l=read();r=read();
            change(l,r,1,s);
            if(t[1].w-t[1].ti<0)
            {
                printf("-1
    %d",i);
                return 0;
            }
        }
        cout<<0;
        return 0;
    }
     
     
  • 相关阅读:
    1058 A+B in Hogwarts (20)
    1036. Boys vs Girls (25)
    1035 Password (20)
    1027 Colors in Mars (20)
    1009. Product of Polynomials (25)
    1006. Sign In and Sign Out
    1005 Spell It Right (20)
    1046 Shortest Distance (20)
    ViewPager页面滑动,滑动到最后一页,再往后滑动则执行一个事件
    IIS7.0上传文件限制的解决方法
  • 原文地址:https://www.cnblogs.com/wybxz/p/12638509.html
Copyright © 2011-2022 走看看