• zjgsu第五场解题报告


    A.hdu1003 Max Sum

    dp求最大序列和

    dp[i] = max(dp[i-1],0)+a[i]  ps.dp[i]当前元素结尾的最大序列和

    mmax = max(mmax,dp[i])

    讲的不清楚,可以看看别人的思路

    http://alorry.blog.163.com/blog/static/6472570820123801223397/

    #include <iostream>
    #include <cstdio>
    #include <cmath>
    #include <cstring>
    using namespace std;
    
    const int MAXN = 1e5+100;
    const int inf = 0x3f3f3f3f;
    int a[MAXN],dp[MAXN];
    
    int main(){
    
        int T;
        scanf("%d",&T);
        int mc = 0;
        while(T--){
            int n;
            scanf("%d",&n);
            int mmax = -inf,l,r,t;
            l = r = 1;
            dp[0] = -1;
            for(int i=1;i<=n;i++){
                scanf("%d",&a[i]);
                if(dp[i-1]>=0){
                    dp[i] = dp[i-1]+a[i];
                    //mmax = max(mmax,dp[i]);
                }else{
                    t = i;
                    dp[i] = a[i];
                }
                if(mmax<dp[i]){
                    mmax = dp[i];
                    l = t;
                    r = i;
                }
            }
            printf("Case %d:
    %d %d %d
    ",++mc,mmax,l,r);
            if(T)cout<<endl;
        }
    
        return 0;
    }
    View Code

    B.hdu2522 A simple problem

    求小数循环节的思路可以看看这个链接

    http://www.cnblogs.com/hxsyl/p/3330481.html

    1/n的循环节最多有(n-1)个数,只要用长除法得到第一次余数重复,前面的的商就是答案

    n也可以是负数

    #include <iostream>
    #include <cstdio>
    #include <cmath>
    #include <cstring>
    
    using namespace std;
    
    const int MAXN = 1e5+100;
    
    int mark[MAXN];
    int ans[MAXN];
    int top,l;
    
    void solve(int x){
        memset(mark,0,sizeof mark);
        top = l = 0;
        int s = 1,t;
        mark[1] = 1;
        while(s){
            t = s*10/x;
            s = s*10%x;
            ans[top++] = t;
            if(mark[s]){
                break;
            }
            mark[s] = 1;
        }
    }
    
    int main()
    {
        int T;
        scanf("%d",&T);
        while(T--){
            int n;
            scanf("%d",&n);
            if(n<0){cout<<"-";n = fabs(n);}
            if(n==1){
                cout<<1<<endl;
                continue;
            }
            solve(n);
            if(n==1){
                cout<<0<<endl;
                continue;
            }
            cout<<"0.";
            for(int i=0;i<top;i++)cout<<ans[i];
            cout<<endl;
    
        }
        //cout << "Hello world!" << endl;
        return 0;
    }
    View Code

    C.hdu1506 Largest Rectangle in a Histogram

     题意:从左到右,对于每个点,记算出他所能向左和向右延伸的最大边界,该长度乘以该点高度就是该点所能呈现的最大值,最后扫描一边找出最大的

    比如2 4 3 4 2 4 ,a3(3)能向左延伸1,向右延伸3,所以a3所能代表的矩阵就是(1+1+3)*3

    #include <iostream>
    #include <cstdio>
    #include <cmath>
    #include <cstring>
    using namespace std;
    typedef long long ll;
    const int MAXN = 1e5+100;
    const int inf = 0x3f3f3f3f;
    int a[MAXN],L[MAXN],R[MAXN];
    
    int main(){
    
        int n;
        while(scanf("%d",&n)!=EOF&&n){
                
            for(int i=1;i<=n;i++){scanf("%d",&a[i]);L[i] = R[i] = i;}
            for(int i=1;i<=n;i++){
                int t = i;
                while(t>=1&&a[i]<=a[t]){
                    L[i] = L[t];
                    t = L[t]-1;
                }
            }
        
            for(int i=n;i>=1;i--){
                int t = i;
                while(t<=n&&a[i]<=a[t]){
                    R[i] = R[t];
                    t = R[t]+1;
                }
            }
            
            ll mmax = -inf;
            for(int i=1;i<=n;i++){
                mmax = max(mmax,(1LL)*a[i]*(R[i]-L[i]+1));
            }
            cout<<mmax<<endl;
        }
    
        return 0;
    }
    View Code

    D.poj3047 Bovine Birthday

    求任意给定日期的是星期几

    蔡勒公式套一下就可以了

    #include <iostream>
    #include <cstdio>
    #include <cmath>
    using namespace std;
    
    typedef long long ll;
    
    /*计算任何日期为周几模板*/
    int fun(int x,int y,int z){
        if(y<3){
            x-=1;
            y+=12;
        }
        int a = x/100,b = x-100*a;
        int w = a/4 - 2*a+b+b/4+(13*(y+1)/5)+z-1;
        w = (w%7+7)%7;
        return w;
    }
    
    int main()
    {
        /*for(int i=1;i<13;i++){
            cout<<fun(2016,i,1)<<" ";
        }
        cout<<endl;*/
        int x,y,z;
        while(scanf("%d%d%d",&x,&y,&z)!=EOF){
            int w = fun(x,y,z);
            if(w==1)cout<<"monday"<<endl;
            else if(w==2)cout<<"tuesday"<<endl;
            else if(w==3)cout<<"wednesday"<<endl;
            else if(w==4)cout<<"thursday"<<endl;
            else if(w==5)cout<<"friday"<<endl;
            else if(w==6)cout<<"saturday"<<endl;
            else cout<<"sunday"<<endl;
        }
        //cout << "Hello world!" << endl;
        return 0;
    }
    View Code

    E.hdu1232 畅通工程

    最小生成树模板套一下就可以了

     http://www.cnblogs.com/EdsonLin/p/5586034.html

    F.poj2603 Brave balloonists

    10个数的乘积sa 的所有因子个数(包括它本身)

    思路:先将一个数可以化做素数的乘积形式

    比如60 = 2^2 * 3^1 * 5^1

    这样'2'可以提供(0,1,2)个2,'3'可以提供(0,1)个3,'5'可以提供(0,1)个5

    所以60的所有因子个数就是 (2+1)*(1+1)*(1+1),ps.如果不包括本身的化最后要减去1

    先打素数表,标记每个素数的个数,然后就可以得到答案

    这题也是上一次的校赛题。。。

    #include <iostream>
    #include <cstdio>
    #include <cmath>
    
    using namespace std;
    
    const int MAXN = 1e4+100;
    
    int a[10];
    int p[MAXN],vis[MAXN],num[MAXN];
    int cnt;
    
    void isprime(){
        cnt = 0;
        for(int i=2;i<MAXN;i++){
            if(!vis[i]){
                p[cnt++] = i;
                for(int j=i*2;j<MAXN;j+=i){
                    vis[j] = 1;
                }
            }
        }
    }
    
    int main(){
    
        isprime();
       // for(int j=0;j<5;j++)cout<<p[j]<<" ";
      // cout<<endl;
        for(int i=0;i<10;i++)scanf("%d",&a[i]);
        //int sum = 0;
        for(int i=0;i<10;i++){
            int t = a[i],k;
            for(int j=0;j<cnt&&p[j]<=t;j++){
                k = 0;
                if(t%p[j]==0){
                    while(t%p[j]==0){
                        t/=p[j];
                        k++;
                    }
                    num[j] += k;
                    //cout<<p[j]<<" ";
                }
            }
        }
        int sum = 1;
        for(int j=0;j<cnt;j++){
            if(num[j]){
                sum *= (1+num[j]);
                sum %= 10;
            }
        }
        //sum = (sum-1+10)%10;
        cout<<sum<<endl;
    
    
        return 0;
    }
    View Code

    G.hdu1563 Find your present!

    题意:如果某个数只有奇数个,那这个数就是特殊数,输出这个数,本题应该只存在一个这样的数

    可以用因为输入的数可能比较大,用数组下标表示的话会爆数组,可以用c++的map

    还有一种方法是用异或 比如 3^5^3^4^4^4^4 最后结果就是3,将该序列异或,最后剩余的结果就是答案

    #include <iostream>
    #include <cstdio>
    #include <cmath>
    
    using namespace std;
    
    const int MAXN = 2e2+100;
    
    int a[MAXN];
    
    int main(){
    
        int n;
        while(scanf("%d",&n)!=EOF&&n){
            int ans = 0;
            for(int i=0;i<n;i++){
                scanf("%d",&a[i]);
                ans ^= a[i];
            }
            cout<<ans<<endl;
        }
    
    
        return 0;
    }
    View Code

    H. hud3351 Seinfeld

    题意:给定一个括号序列,可以改变任意括号的方向,要求改变的数目最少,最后使得这个序列的括号完全配对 ps.题目给的序列应该就是偶数的

    思路:括号配对应该想到栈操作,比如比如输入{ { { { } { } { } } { , 自己模拟这个过程,按顺序压入栈中,如果栈顶top是{,当前i要压入的的是 },则说明这两个已经匹配,将栈顶元素弹出,当前元素变为i+1

    同颜色消除就是这个过程

    最后在栈里面的元素必然只有两种情况

    1.{{{{{{{ 全部都为{

    2.}}}}{{{{{{{  靠栈底都是} 靠栈底都是{

    t1表示}个数 t2表示{个数

    则最后最小的改变数量是sum = (t1+1)/2+(t2+1)2

    ps.t1为奇数 t2必然也为奇数

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <cmath>
    #include <cstdlib>
    #include <algorithm>
    #include <string>
    #include <stack>
    #include <queue>
    
    const int inf = (1<<31)-1;
    const int MAXN = 1e5+10;
    
    using namespace std;
    
    stack<char>a;
    int main()
    {
        string s1;
        int mc=1;
        while(cin>>s1&&s1[0]!='-'){
            int n = s1.length();
            for(int i=0;i<n;i++){
                if(a.empty()){
                    a.push(s1[i]);
                }else{
                    if(a.top()=='{'&&s1[i]=='}')
                        a.pop();
                    else
                        a.push(s1[i]);
                }
            }
            int t1,t2;
            t1 = t2 = 0;
            while(!a.empty()){
                if(a.top()=='{')
                    t1++;
                else
                    t2++;
                a.pop();
            }
            cout<<mc++<<". ";
            cout<<(t1+1)/2+(t2+1)/2<<endl;
        }
        //cout << "Hello world!" << endl;
        return 0;
    }
    View Code

    I.poj1088 滑雪

    dp+dfs 找到最长递减序列

    dp[i][j] = max(dp[i-1][j],dp[i+1][j-1],d[i][j-1],dp[i][j+1]

    J. uva1416 Warfare And Logistics

    构造单源最短路径树

    解题报告:http://www.cnblogs.com/EdsonLin/p/5483408.html

    在一个谎言的国度,沉默就是英雄
  • 相关阅读:
    redis zset 延迟合并任务处理
    String忽略大小写方法compareToIgnoreCase源码及Comparator自定义比较器
    dotnet 使用 ConfigureAwait.Fody 库设置默认的 await 同步上下文切换配置
    dotnet 解析 TTF 字体文件格式
    Total Commander 使用 mklink 建立文件夹链接 将 C 盘文件迁移到其他盘
    dotnet OpenXML 解析 PPT 图表 解析日期时间表示内容
    dotnet 使用 IndentedTextWriter 辅助生成代码时生成带缩进的内容
    dotnet 读 WPF 源代码笔记 为什么自定义的 UserControl 用户控件不能跨程序集继承
    dotnet 使用 TaskTupleAwaiter 同时等待多个任务简化代码写法
    dotnet OpenXML 解析 PPT 图表 面积图入门
  • 原文地址:https://www.cnblogs.com/EdsonLin/p/5734363.html
Copyright © 2020-2023  润新知