• 山东省第五届ACM省赛


    相关总结:http://www.cnblogs.com/mcflurry/p/3724649.html#3395978

    A.angry_birds_again_and_again(定积分)

    B.Circle(高斯消元?/递推)

    C.Colorful Cupcakes(dp?)

    D.Devour Magic(线段树)

    E.Factorial(10以内阶乘)

    F.Full Binary Tree(二叉树)

    G.Hearthstone II(dp)

    H.Painting Cottages(几何)

    I.Tree()

    J.Weighted Median(sort排序)

    A.angry_birds_again_and_again

    d.求面积

    s.设抛物线方程y=a*x^2+bx+c,求出a、b,定积分求面积。

    #include<iostream>
    #include<stdio.h>
    #include<math.h>
    using namespace std;
    
    int main(){
    
        int T;
        double px,tx,alfa;
        double a,b;
        double area,area1,area2;
    
        scanf("%d",&T);
    
        while(T--){
    
            scanf("%lf%lf%lf",&px,&tx,&alfa);
    
            b=tan(alfa);
    
            a=(b*px)/(tx*tx-2*tx*px);
    
            area1=(a/3)*(tx*tx*tx)+(b/2)*(tx*tx);//抛物线面积
            area2=((a*(tx*tx)+b*tx)*(px-tx))/2;//三角形面积
            area=area1+area2;
    
            printf("%.3f
    ",area);
    
        }
    
        return 0;
    }
    View Code

    B.Circle

    d.n个数围成一个圈,编号0~n-1,从一个数到其上一个和下一个的数的概率相同(即都是0.5)。给出n,求从0出发到达一个数x所需要的步数的数学期望。

    s.据说可以用高斯消元?

    这里用递推可以水一下。

    首先可以确定三个结论(1.d[i]=0.5*d[i+1]+0.5*d[i-1] , 2.d[n]=d[0]=0 , 3.d[i]=d[n-i])

    另外,某大神从小数找到一个规律。。。

    d[0]=0,d[1]=n-1,d[2]=(n-1)+(n-3),d[3]=(n-1)+(n-3)+(n-5),……。

    这样就可以递推了。

    ps:遇到这种像是数学的题,找不到什么思路时,写出一些小的数据,发现有没有什么规律!

    第六届的时候,我记得那个像是博弈的题,虎三就从中找到规律。。。当大于某个数的时候,答案就确定了!!

    所以说,记得找规律。

    c.递推水一下。。。

    #include<iostream>
    #include<stdio.h>
    using namespace std;
    
    int main(){
    
        int T;
        int n,x;
        int i;
        double d[1005];
        d[0]=0;
    
        scanf("%d",&T);
    
        while(T--){
    
            scanf("%d%d",&n,&x);
    
            if(x>n/2){
                x=n-x;
            }
    
            for(i=1;i<=x;++i){
                d[i]=d[i-1]+(n-(2*i-1));//这个递推公式很神奇。。。
            }
    
            printf("%.4f
    ",d[x]);
    
        }
    
        return 0;
    }
    View Code

    C.Colorful Cupcakes

    http://blog.csdn.net/cds225255/article/details/43805745

    http://blog.csdn.net/codebattle/article/details/43820359

    D.Devour Magic

    d.n个单位,每个单位每秒增加1法力,在某些时间取走一些区间的法力值(取走之后该区间所有单位的法力变为0),求取得的所有法力值。

    s.线段树。区间更新,区间求和。不过这个题来说,区间求和之后要把该区间清零。set+add操作,set在先,add在后

    c.注意一下要用long long。敲了一天,终于敲对了~

    #include<iostream>
    #include<stdio.h>
    #include<string.h>
    using namespace std;
    
    #define L(root) ((root)<<1)
    #define R(root) (((root)<<1)|1)
    
    const int MAXN=1e5+10;//
    int numbers[MAXN];//初始值
    
    struct node{
        int left,right;//
        long long sum;
        int delta;
        int v;//区间里的数设为v
        bool flag;//标记是否设置为v
        int mid(){
            return left+((right-left)>>1);
        }
    }tree[MAXN*4];//4倍空间
    
    void pushUp(int root){
        tree[root].sum=tree[L(root)].sum+tree[R(root)].sum;
    }
    
    void pushDown(int root){
        if(tree[root].flag){
            tree[L(root)].delta=tree[R(root)].delta=0;
            tree[L(root)].v=tree[R(root)].v=tree[root].v;
            tree[L(root)].flag=tree[R(root)].flag=true;
            tree[L(root)].sum=tree[root].v*(tree[L(root)].right-tree[L(root)].left+1);
            tree[R(root)].sum=tree[root].v*(tree[R(root)].right-tree[R(root)].left+1);
            tree[root].flag=false;
        }
        if(tree[root].delta){
            tree[L(root)].delta+=tree[root].delta;
            tree[R(root)].delta+=tree[root].delta;
            tree[L(root)].sum+=tree[root].delta*(tree[L(root)].right-tree[L(root)].left+1);
            tree[R(root)].sum+=tree[root].delta*(tree[R(root)].right-tree[R(root)].left+1);
            tree[root].delta=0;
        }
    }
    
    void build(int root,int left,int right){
        tree[root].left=left;
        tree[root].right=right;
        tree[root].delta=0;
        tree[root].flag=false;
        if(left==right){
            tree[root].sum=numbers[left];
            return;
        }
        int mid=tree[root].mid();
        build(L(root),left,mid);
        build(R(root),mid+1,right);
        pushUp(root);
    }
    
    long long query(int root,int left,int right){
        if(tree[root].left==left&&tree[root].right==right){
            return tree[root].sum;
        }
        pushDown(root);
        int mid=tree[root].mid();
        if(right<=mid){
            return query(L(root),left,right);
        }
        else if(left>mid){
            return query(R(root),left,right);
        }
        else{
            return query(L(root),left,mid)+query(R(root),mid+1,right);
        }
    }
    
    void update(int root,int left,int right,int add){
        if(tree[root].left==left&&tree[root].right==right){
            tree[root].delta+=add;
            tree[root].sum+=add*(right-left+1);
            return;
        }
        pushDown(root);
        int mid=tree[root].mid();
        if(right<=mid){
            update(L(root),left,right,add);
        }
        else if(left>mid){
            update(R(root),left,right,add);
        }
        else{
            update(L(root),left,mid,add);
            update(R(root),mid+1,right,add);
        }
        pushUp(root);
    }
    
    void setf(int root,int left,int right,int v){
        if(tree[root].left==left&&tree[root].right==right){
            tree[root].delta=0;
            tree[root].sum=v*(right-left+1);
            tree[root].v=v;
            tree[root].flag=true;
            return;
        }
        pushDown(root);
        int mid=tree[root].mid();
        if(right<=mid){
            setf(L(root),left,right,v);
        }
        else if(left>mid){
            setf(R(root),left,right,v);
        }
        else{
            setf(L(root),left,mid,v);
            setf(R(root),mid+1,right,v);
        }
        pushUp(root);
    }
    
    int main(){
    
        memset(numbers,0,sizeof(numbers));
    
        int T;
        int n,m;
        int t,l,r;
        int i;
        int lastTime;
        long long sum;
    
        scanf("%d",&T);
    
        while(T--){
    
            scanf("%d%d",&n,&m);
            build(1,1,n);
    
            lastTime=0;
            sum=0;
            for(i=0;i<m;++i){
                scanf("%d%d%d",&t,&l,&r);
    
                update(1,1,n,t-lastTime);
                sum+=query(1,l,r);
                setf(1,l,r,0);//l到r区间设为0
    
                lastTime=t;
            }
    
            printf("%lld
    ",sum);
    
        }
    
        return 0;
    }
    View Code

    E.Factorial

    d.求10以内的阶乘

    s.打表

    #include<iostream>
    #include<stdio.h>
    using namespace std;
    
    int main(){
    
        int factorial[11];
        int i;
        int T;
        int n;
    
        factorial[0]=1;
        for(i=1;i<=10;++i){
            factorial[i]=factorial[i-1]*i;
        }
    
        scanf("%d",&T);
    
        while(T--){
            scanf("%d",&n);
            printf("%d
    ",factorial[n]);
        }
    
        return 0;
    }
    View Code

    F.Full Binary Tree

    d.在满二叉树中求两个节点的最近距离

    s.顺着向上找,直到找到最近公共祖先即可。

    #include<iostream>
    #include<stdio.h>
    using namespace std;
    
    int main(){
    
        int n;
        int u,v;
        int ans;
    
        scanf("%d",&n);
    
        while(n--){
    
            scanf("%d%d",&u,&v);
    
            ans=0;
            while(u!=v){
                if(u>v){
                    u/=2;
                }
                else{
                    v/=2;
                }
                ++ans;
            }
    
            printf("%d
    ",ans);
    
        }
    
        return 0;
    }
    View Code

    G.Hearthstone II

    d.n场比赛,m个场地,m<=n,1场比赛只能选择1个场地,要求每个场地必须使用过一次,求所有的方案数。

    s.乍一看有点像组合数学,应该也能解吧?

    这里可以用动态规划来做,

    法1:

    dp[i][j]表示:前i场比赛用了j个场地的情况数

    dp[i][j]=dp[i-1][j]*j+dp[i-1][j-1]*(m-j+1);

    法2:

    dp[i][j]表示:前i场比赛用了‘前’j个场地的情况数

    注意是‘前’j个场地,这样的话,最后需要乘上场地数目的全排列

    dp[i][j]=dp[i-1][j]*j+dp[i-1][j-1];

    c.法1

    /*
    dp[i][j]=dp[i-1][j]*j+dp[i-1][j-1]*(m-j+1);
    */
    #include<iostream>
    #include<stdio.h>
    #include<string.h>
    using namespace std;
    
    const int MOD=1e9+7;
    
    int main(){
    
        int n,m;
        long long dp[105][105];//dp[i][j]表示:前i场比赛用了j个场地的情况数
        int i,j;
    
        while(~scanf("%d%d",&n,&m)){
    
            memset(dp,0,sizeof(dp));
            for(i=1;i<=n;++i){
                //j=1;
                //前i场比赛用了1个场地,初始化为m
                dp[i][1]=m;
            }
            for(i=2;i<=n;++i){
                for(j=2;j<=i&&j<=m;++j){
                    dp[i][j]=((dp[i-1][j]*j)%MOD+(dp[i-1][j-1]*(m-j+1))%MOD)%MOD;
                }
            }
    
            printf("%lld
    ",dp[n][m]);
        }
    
        return 0;
    }
    View Code

    c2.法2

    /*
    dp[i][j]=dp[i-1][j]*j+dp[i-1][j-1];
    */
    #include<iostream>
    #include<stdio.h>
    #include<string.h>
    using namespace std;
    
    const int MOD=1e9+7;
    
    int main(){
    
        int n,m;
        long long dp[105][105];//dp[i][j]表示:前i场比赛用了‘前’j个场地的情况数
        int i,j;
        long long factorial[105];
    
        factorial[1]=1;
        for(i=2;i<105;++i){
            factorial[i]=(factorial[i-1]*i)%MOD;
        }
    
        while(~scanf("%d%d",&n,&m)){
    
            memset(dp,0,sizeof(dp));
            for(i=1;i<=n;++i){
                //j=1;
                //前i场比赛用了第1个场地,初始化为1
                dp[i][1]=1;
            }
            for(i=2;i<=n;++i){
                for(j=2;j<=i&&j<=m;++j){
                    dp[i][j]=((dp[i-1][j]*j)%MOD+dp[i-1][j-1])%MOD;
                }
            }
    
            printf("%lld
    ",(dp[n][m]*factorial[m])%MOD);
        }
    
        return 0;
    }
    View Code

    H.Painting Cottages

    I.Tree

    J.Weighted Median

    d.求和

    s.排序,求和

    c.sum2>sum中,用>而不是>=,处理0.5的小数。下面的方法更方便,学习了!

    #include<iostream>
    #include<stdio.h>
    #include<algorithm>
    using namespace std;
    
    const int MAXN=1e7+5;
    
    struct node{
        long long x;
        long long w;
    }p[MAXN];
    
    bool cmp(node a,node b){
        return a.x<b.x;
    }
    
    int main(){
    
        int n;
        long long x,w;
        int i;
        long long sum;
        long long sum2;
    
        while(~scanf("%d",&n)){
    
            sum=0;
    
            for(i=0;i<n;++i){
                scanf("%lld",&x);
                p[i].x=x;
            }
            for(i=0;i<n;++i){
                scanf("%lld",&w);
                p[i].w=w;
                sum+=w;
            }
    
            sort(p,p+n,cmp);
    
            sum/=2;
            sum2=0;
            for(i=0;i<n;++i){
                sum2+=p[i].w;
                if(sum2>sum)break;//此处大于号是因为处理0.5的小数
            }
    
            printf("%lld
    ",p[i].x);
    
        }
    
        return 0;
    }
    View Code

    ps:==...,好像不对,比如这组数据

    4

    1 2 3 4

    1 1 1 1

    正确答案为:2

    上述代码为:3

    GG,仗着数据弱,过了。。。汗。

    还是直接用下面的方法吧。

    c2.直接*2处理,避免了总和为奇数。

    #include<iostream>
    #include<stdio.h>
    #include<algorithm>
    using namespace std;
    
    const int MAXN=1e7+5;
    
    struct node{
        long long x;
        long long w;
    }p[MAXN];
    
    bool cmp(node a,node b){
        return a.x<b.x;
    }
    
    int main(){
    
        int n;
        long long x,w;
        int i;
        long long sum;
        long long sum2;
    
        while(~scanf("%d",&n)){
    
            sum=0;
    
            for(i=0;i<n;++i){
                scanf("%lld",&x);
                p[i].x=x;
            }
            for(i=0;i<n;++i){
                scanf("%lld",&w);
                p[i].w=w*2;//*2处理
                sum+=w*2;//*2处理
            }
    
            sort(p,p+n,cmp);
    
            sum/=2;
            sum2=0;
            for(i=0;i<n;++i){
                sum2+=p[i].w;
                if(sum2>=sum)break;//由于上面*2处理了,此处要用>=了
            }
    
            printf("%lld
    ",p[i].x);
    
        }
    
        return 0;
    }
    View Code
  • 相关阅读:
    Cannot find class [org.springframework.http.converter.json.MappingJacksonHttpMessageConverter]
    HTTP的长连接和短连接
    Nginx(三)nginx 反向代理
    Nginx(四)nginx 负载均衡
    postgresql 数据库 INSERT 或 UPDATE 大量数据时速度慢的原因分析
    低层次父母,喜欢不停地“讲道理”,而高层次父母,会做2件事
    oracle数据库数据量如何计算,怎么查看oracle数据库数据量大小?
    Git的eclipse插件(下载、抓取、提交、恢复、比较)
    Linux 上 定时备份postgresql 数据库的方法
    Nginx(二)nginx.conf 配置文件
  • 原文地址:https://www.cnblogs.com/gongpixin/p/5327865.html
Copyright © 2020-2023  润新知