zoukankan      html  css  js  c++  java
  • 北京信息科技大学第11届程序设计基本技能比赛

    北京信息科技大学第11届程序设计基本技能比赛

    A. 太阳花田

    ​ 题意:一个圆和一个长为x,高为y的矩形最大交集是多少?

    ​ 题解:分类讨论,显然四种情况,不妨假设x是短边。第一种,圆被矩形完全包含,(r<x/2),答案是圆的面积。第二种,圆露出去了两边(r<y/2),这里可以一个圆减去一个扇形,但是要加回来两个三角形,三角形的部分是简单三角函数计算。第三种就是露出去四个部分(r<sqrt(x/2*x/2+y/2*y/2)),同样是减去四个扇形,加回来四个三角形。最后一种情况,全部包含。

    #include <bits/stdc++.h> //万能头
    
    double x, y, r;
    
    const double pi = acos(-1.0); //高精度pi
    
    using namespace std;
    
    int main(){
        cin>>x>>y>>r;
        if(y<x)swap(x,y);
    
        if(r<=x/2){
            printf("%.2f",pi*r*r);
        }else if (r<y/2){
            double ang = 2*acos(0.5*x/r);
            double l = ang*r;
            double s = l*r;
            s-=x*tan(ang/2)*x/2;
            printf("%.2f",pi*r*r-s);
        }else if(r*r<(x/2)*(x/2)+(y/2)*(y/2)){
            double ang=2*acos(0.5*x/r);
            double l=ang*r;
            double s=l*r;
            s-=x*tan(ang/2)*x/2;
    
            double ang1=2*acos(0.5*y/r);
            double l1=ang1*r;
            double s1=l1*r;
            s1-=y*tan(ang1/2)*y/2;
            printf("%.2f",pi*r*r-s-s1);
        }else{
            printf("%.2f",x*y);
        }
    
        return 0;
    }
    
    

    B. 算数教室

    ​ 题意:给两个长度为n的数组,是否存在两个下标a[i]+b[j]=target。

    ​ 题解:set存一下a[i],对b中每一个元素,查询一下set中是否有target-b[i]即可(即查询是否存在b[j]=target-a[i]),这样复杂度能够接受。

    #include<bits/stdc++.h>
    
    using namespace std;
    
    int n, m, x;
    
    set<int> S;
    
    int main(){
        scanf("%d%d%d",&n,&m,&x);
    
        for(int i=1;i<=n;++i)S.insert(x);
        for(int i=1;i<=m;++i){
            int t;scanf("%d",&t);
            if(S.count(x-t)){
                cout<<"YES";
                return 0;
            }
        }
        cout<<"NO";
    
        return 0;
    }
    
    

    C. 博丽神社

    ​ 题意:过原点的直线有多少条,能使得所有的点与关于这条之间对称。

    ​ 题解:检查过每个点,和每两个点之间的中垂线。去重可以用pair<int,int>。这表示一个方向向量,细节看代码。

    #include<bits/stdc++.h>
    
    #define all(x) x.begin(),x.end()
    #define fi first
    #define sd second
    #define lson (nd<<1)
    #define rson (nd+nd+1)
    #define PB push_back
    #define mid (l+r>>1)
    #define MP make_pair
    #define SZ(x) (int)x.size()
    
    using namespace std;
    
    typedef long long LL;
    
    typedef vector<int> VI;
    
    typedef pair<int,int> PII;
    
    inline int read(){
        int res=0, f=1;char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
        while(ch>='0'&&ch<='9'){res=res*10+ch-'0';ch=getchar();}
        return res*f;
    }
    
    const int N = 105;
    
    const int MOD = 1000000007;
    
    template<typename T>
    void chmin(T& a, T b){if(a>b)a=b;}
    
    template<typename T>
    void chmax(T& a, T b){if(b>a)a=b;}
    
    int n;
    
    struct point{
        int x, y;
        point(){}
        point(int _x, int _y){
            x=_x,y=_y;
        }
    };
    
    point pts[N];
    
    point operator-(point a, point b){
        return point(a.x-b.x,a.y-b.y);
    }
    
    point operator+(point a, point b){
        return point(a.x+b.x,a.y+b.y);
    }
    
    const double eps = 1e-8;
    
    set<PII> isExist;
    
    int vis[N];
    
    LL dot(point a, point b){
        return 1ll*a.x*b.x+1ll*a.y*b.y;
    }
    
    double L(point a){
        return sqrt(1.0*a.x*a.x+1.0*a.y*a.y);
    }
    
    bool check(point v){
        memset(vis,0,sizeof vis);
        for(int i=1;i<=n;++i){
            if(vis[i])continue;
            for(int j=1;j<=n;++j){
                if(vis[j])continue;
                point m=pts[i]+pts[j];
                point d=pts[i]-pts[j];
                if(dot(d,v)!=0)continue;
                else if(abs(abs(dot(m,v))-L(m)*L(v))>eps)continue;
                else{
                    vis[i]=vis[j]=1;
                }
            }
        }
    
        bool ok=1;
        for(int i=1;i<=n;++i)if(!vis[i])ok=0;
        return ok;
    }
    
    int main(){
        n=read();
        for(int i=1;i<=n;++i){
            int xx=read(),yy=read();
            pts[i]=point(xx,yy);
        }
    
        int res=0;
        for(int i=1;i<=n;++i){
            int xx=pts[i].x,yy=pts[i].y;
            if(xx&&yy){
                int g=__gcd(xx,yy);
                xx/=g;yy/=g;
            }else{
                if(!xx)yy=1;
                else xx=1;
            }
            if(isExist.count(MP(xx,yy)))continue;
            if(check(point(xx,yy)))++res;
            isExist.insert(MP(xx,yy));
        }
    
        for(int i=1;i<=n;++i){
            for(int j=i+1;j<=n;++j){
                point m=pts[i]+pts[j];//中点都被放大两倍
                point v=pts[i]-pts[j];
                if(dot(m,v)!=0)continue;
                else{
                    int& xx=m.x,&yy=m.y;
                    if(!xx&&!yy)xx=v.y,yy=-v.x;
    
                    if(xx&&yy){
                        int g=__gcd(xx,yy);
                        xx/=g;yy/=g;
                    }else{
                        if(!xx)yy=1;
                        else xx=1;
                    }
    
                    if(isExist.count(MP(xx,yy)))continue;
                    if(check(m)){
                        ++res;
                        isExist.insert(MP(xx,yy));
                    }
                }
            }
        }
    
        cout<<res;
        return 0;
    }
    
    

    D. 小小的百鬼夜行

    ​ 题意:把一个字符串复制k次,然后看其中出现最多的字母出现次数。

    ​ 题解:先数一下每一个字符出现次数,然后乘以k,要注意会爆int,开long long。

    #include<bits/stdc++.h>
    
    using namespace std;
    
    inline int read(){
        int res=0, f=1;char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
        while(ch>='0'&&ch<='9'){res=res*10+ch-'0';ch=getchar();}
        return res*f;
    }
    
    const int MAXN = 200005;
    
    int buk[26];
    char s[MAXN];
    int n, k;
    
    int main(){
        n=read(),k=read();
        scanf("%s",s+1);
    
        for(int i=1;i<=n;++i)++buk[s[i]-'a'];
        int mx=*max_element(buk,buk+26);
        cout<<1ll*mx*k;
        return 0;
    }
    
    

    E. 贪玩的二小姐

    ​ 题意:每次翻转长度为m的区间,并且翻转的区间左端点一直往后,每次翻转输出和。

    ​ 题解:可以双端队列,但是蒟蒻只会抄板子。splay维护区间,不会的可以去luogu刷一刷模板题

    #include<bits/stdc++.h>
    
    using namespace std;
    
    const int N = 1000005;
    const int inf = 1e8;
    
    #define ls(x) (bst[x].ch[0])
    #define rs(x) (bst[x].ch[1])
    #define getKey(x) (bst[x].key)
    #define getSize(x) (bst[x].sz)
    #define getFather(x) (bst[x].f)
    
    typedef long long LL;
    
    struct splayNode{
        int ch[2];
        int f;
        int sz;
        int key;
        int rev;
        LL sum;
        void clear(){ch[0]=ch[1]=f=rev=0;}
    }bst[N];
    
    inline bool getDir(int x){return rs(getFather(x))==x;}
    
    int rt, cntNode, top, a[N], id[N], rub[N], n, m, q;
    
    inline int read(){
        int x=0,f=1;char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
        while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
        return x*f;
    }
    
    int getId(){//防止节点过多,我们需要设置一个垃圾堆,有废弃的节点应该优先使用
        if(top==0)return ++cntNode;
        return rub[top--];
    }
    
    void changeRev(int nd){
        swap(ls(nd),rs(nd));
        bst[nd].rev^=1;
    }
    
    void pushup(int nd){
        splayNode& x=bst[bst[nd].ch[0]], &y=bst[bst[nd].ch[1]];
        splayNode& res=bst[nd];
        int val=bst[nd].key;
    
        res.sum=x.sum+y.sum+val;
        res.sz=x.sz+y.sz+1;
    }
    
    void pushdown(int nd){
        if(bst[nd].rev){
            changeRev(ls(nd));
            changeRev(rs(nd));
            bst[nd].rev=0;
        }
    }
    
    void rot(int nd){
        int fa=getFather(nd),gf=getFather(fa);
        int ws=getDir(nd),ws1=getDir(fa);
    
        int nd1=bst[nd].ch[ws^1];
    
        bst[fa].ch[ws]=nd1;bst[nd1].f=fa;
        bst[gf].ch[ws1]=nd;bst[nd].f=gf;
        bst[nd].ch[ws^1]=fa;bst[fa].f=nd;
        pushup(fa);pushup(nd);
    }
    
    void splay(int nd, int goal=0){
        while(getFather(nd)!=goal){
            int fa=getFather(nd);
            int gf=getFather(fa);
            if(gf!=goal){
                if(getDir(nd)==getDir(fa))rot(fa);
                else rot(nd);
            }
    
            rot(nd);
        }
        if(!goal)rt=nd;
    }
    
    int kth(int k){
        int nd=rt;
        while(1){
            pushdown(nd);
            if(getSize(ls(nd))>=k)nd=ls(nd);
            else if(k==getSize(ls(nd))+1)return nd;
            else{
                k-=getSize(ls(nd))+1;
                nd=rs(nd);
            }
        }
    }
    
    int split(int s, int len){//拆出响应的区间
        int x=kth(s),y=kth(s+len+1);
        splay(x,0);splay(y,x);
    
        return ls(y);
    }
    
    void newNode(int nd, int x){//newc出一新节点
        bst[nd].sum=x;
        bst[nd].rev=0;
        bst[nd].sz=1;
    }
    
    void build(int s, int e, int fa){
        int mid=(s+e)>>1;int curNode=id[mid],pre=id[fa];
        if(s==e){
            newNode(curNode,a[s]);
        }
    
        if(s<mid)build(s,mid-1,mid);
        if(mid<e)build(mid+1,e,mid);
        bst[curNode].key=a[mid];bst[curNode].f=pre;
        pushup(curNode);
        bst[pre].ch[mid>=fa]=curNode;
    }
    
    void reverseTree(int x, int len){
        int nd=split(x,len),y=getFather(nd);
        changeRev(nd);
        pushup(y);pushup(getFather(y));
    }
    
    LL query(int x, int len){//求和
        int nd=split(x,len);
        return bst[nd].sum;
    }
    
    int main(){
        n=read(),m=read();
        a[1]=a[n+2]=-inf;
    
        for(int i=2;i<=n+1;++i)a[i]=read();
        for(int i=1;i<=n+2;++i)id[i]=i;
        build(1,n+2,0);
    
        rt=(n+3)>>1;cntNode=n+2;
    
        q = read();
        while(q--){
            int s = read();
            cout<<query(s,m);
            cout<<" 
    "[q==0];
            reverseTree(s,m);
        }
    
        return 0;
    }
    
    
    

    F. 帕秋莉,go!

    ​ 题意:给一些字符串,构造字典序最大的回文串。

    ​ 题解:显然,奇数个的只能有一个,选最大的放中间,其他的偶数个按照从大到小从两端开始放就能通过。

    #include<bits/stdc++.h>
    
    #define all(x) x.begin(),x.end()
    #define fi first
    #define sd second
    #define lson (nd<<1)
    #define rson (nd+nd+1)
    #define PB push_back
    #define mid (l+r>>1)
    #define MP make_pair
    #define SZ(x) (int)x.size()
    
    using namespace std;
    
    typedef long long LL;
    
    typedef vector<int> VI;
    
    inline int read(){
        int res=0, f=1;char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
        while(ch>='0'&&ch<='9'){res=res*10+ch-'0';ch=getchar();}
        return res*f;
    }
    
    const int N = 200005;
    
    int buk[26], n;
    
    char str[N];
    
    int main(){
        n=read();
        scanf("%s", str+1);
        for(int i=1;i<=n;++i)++buk[str[i]-'a'];
    
        VI s, e;
    
        for(int i=25;i>=0;--i){
            for(int id=1;id<=buk[i]/2;++id){
                s.PB(i);
                e.PB(i);
            }
            buk[i]= buk[i]&1;
        }
    
        reverse(all(e));
        string res;
        for(int i=0;i<SZ(s);++i)res+=s[i]+'a';
        for(int i=25;i>=0;--i){
            if(buk[i]){
                res+=i+'a';
                break;
            }
        }
        for(int i=0;i<SZ(e);++i)res+=e[i]+'a';
    
        cout<<SZ(res)<<endl;
        cout<<res;
    
    
        return 0;
    }
    
    

    G. 三月精和子序列

    ​ 题意:取三个不同角标,(i,j,k),满足(i<j<k),且(s[i],s[j],s[k])互不相等。

    ​ 题解:对每一个字母分别考虑,枚举字母,然后把字母出现次数乘起来就可以了,注意取模。

    #include<bits/stdc++.h>
    
    using namespace std;
    
    typedef long long LL;
    
    typedef vector<int> VI;
    
    typedef pair<int,int> PII;
    
    inline int read(){
        int res=0, f=1;char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
        while(ch>='0'&&ch<='9'){res=res*10+ch-'0';ch=getchar();}
        return res*f;
    }
    
    const int N = 1000005;
    
    const int MOD = 1000000007;
    
    int buk[26];
    int n;
    char s[N];
    
    int main(){
        n=read();
        scanf("%s",s+1);
    
        for(int i=1;i<=n;++i)++buk[s[i]-'a'];
    
        int ans=0;
    
        for(int i=0;i<26;++i){
            for(int j=i+1;j<26;++j){
                for(int k=j+1;k<26;++k){
                    ans+=(1ll*buk[i]*buk[j]*buk[k])%MOD;
                    ans%=MOD;
                }
            }
        }
        cout<<ans;
    
        return 0;
    }
    
    
    

    H. 小町的烦恼

    ​ 题意:初始值x,每一天这个值都变成前一天的平方倍。

    ​ 题解:答案是(x^{2^{n}})。考虑快速幂和欧拉降幂。分母的模数应该取(MOD-1)

    #include<bits/stdc++.h>
    
    using namespace std;
    
    typedef long long LL;
    
    inline LL read(){
        LL res=0, f=1;char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
        while(ch>='0'&&ch<='9'){res=res*10+ch-'0';ch=getchar();}
        return res*f;
    }
    
    LL x, n;
    
    LL powmod(LL x, LL y, LL MOD){
        LL res=1;
        while(y){
            if(y&1)
                res=res*x%MOD;
            x=x*x%MOD;
            y>>=1;
        }
    
        return res;
    }
    
    int main(){
        x=read(),n=read();
        int MOD = 1e9+7;
        cout<<powmod(x%MOD,powmod(2,n-1,MOD-1),MOD);
    
        return 0;
    }
    
    
  • 相关阅读:
    java的类继承(与c++对比)
    java的数据类型、自动拆装箱、字面量
    java中关键字static和final
    JVM之JIT
    java之JIT(Just in time)
    栈和堆
    C++中vector的使用
    canvas
    ajax笔记
    CSS笔记
  • 原文地址:https://www.cnblogs.com/JohnRan/p/13054012.html
Copyright © 2011-2022 走看看