zoukankan      html  css  js  c++  java
  • p1802,p1806,p1808

      新高一第二期培训开始了,虽然不是我的班也来快乐了.早上来的时候见到了新高一去军训的场面,还挺感动的.

      然后上午并没人问我,我就在校oj刷题,一上午整了三道,美滋滋.

      

       p1802一看就是一个动态规划.考虑每个树能取的状态和前一个树相关,而且不止与前一个树高度相关,还和前前一个树相关.所以我设了四个状态表示当前树的高度和与前一个树的关系.分别是:最低,中等且前一个树更高,中等且前一个树更低,最高.

       这样就可以开始转移了,但是如果给f[1]的四个状态都赋值就会使得最后的答案不明确,因为成环的原因嘛.那么可以考虑关于一树的状态再分状态.f[i][j][k]表示1树状态为j,树i状态为k时的最大观赏值.转移也很好转移,答案是f[n][1..4][1..4]中的最大值.但是我懒省事就复制粘贴了四个.

    long long a[100010][5],f[100010][5];
    long long maxx(long long a,long long b,long long c)
    {
        a=a>b?a:b;
        return a>c?a:c;
    }
    int main()
    {
        int n=read();
        for(int i=1;i<=n;i++)
        {
            a[i][1]=read();
            a[i][2]=read();
            a[i][3]=read();
        }    
        //1:
        f[1][1]=a[1][1];
        f[1][2]=f[1][3]=f[1][4]=-10000000;
        for(int i=2;i<=n;i++)
        {
            f[i][1]=a[i][1]+max(f[i-1][4],f[i-1][3]);
            f[i][2]=a[i][2]+f[i-1][4];
            f[i][3]=a[i][2]+f[i-1][1];
            f[i][4]=a[i][3]+max(f[i-1][1],f[i-1][2]);
        }
        long long ans;
        ans=max(f[n][3],f[n][4]);
        //2
        f[1][2]=a[1][2];
        f[1][1]=f[1][3]=f[1][4]=-10000000;
        
        for(int i=2;i<=n;i++)
        {
            f[i][1]=a[i][1]+max(f[i-1][4],f[i-1][3]);
            f[i][2]=a[i][2]+f[i-1][4];
            f[i][3]=a[i][2]+f[i-1][1];
            f[i][4]=a[i][3]+max(f[i-1][1],f[i-1][2]);
        }
        ans=max(ans,f[n][4]);
        //3
        f[1][3]=a[1][2];
        f[1][1]=f[1][2]=f[1][4]=-10000000;
        for(int i=2;i<=n;i++)
        {
            f[i][1]=a[i][1]+max(f[i-1][4],f[i-1][3]);
            f[i][2]=a[i][2]+f[i-1][4];
            f[i][3]=a[i][2]+f[i-1][1];
            f[i][4]=a[i][3]+max(f[i-1][1],f[i-1][2]);
        }
        ans=max(ans,f[n][1]);
        //4
        f[1][4]=a[1][3];
        f[1][1]=f[1][2]=f[1][3]=-10000000;    
        for(int i=2;i<=n;i++)
        {
            f[i][1]=a[i][1]+max(f[i-1][4],f[i-1][3]);
            f[i][2]=a[i][2]+f[i-1][4];
            f[i][3]=a[i][2]+f[i-1][1];
            f[i][4]=a[i][3]+max(f[i-1][1],f[i-1][2]);
        }
        ans=maxx(ans,f[n][1],f[n][2]);
        cout<<ans;
        return 0;
    }
    p1802

      p1806读懂了题意后考虑不写程序的话普通人会怎么做.应该先看最后一位能不能++,如果能就++走人,否则看倒数第二位能不能++,并且使得倒数第一位为倒数第二位原来的字母+2.如果能就这样做,以此类推.

      那么对于第i位只需判断是否w-i<t-ans[i].如果可以就枚举后面所有位,使得ans[j]=ans[j-1]+1;.

    char s,t;
    int w;
    char ans[30];
    void work()
    {
        for(int i=w;i;i--)
            if(ans[i]<t&&w-i<t-ans[i])
            {
                ans[i]=ans[i]+1;    
                for(int j=i+1;j<=w;j++)
                    ans[j]=ans[j-1]+1;
                return ;
            }
        exit(0);
    }
    int main()
    {
        s=read()+'a'-1;t=read()+'a'-1;w=read();
        for(int i=1;i<=w;i++)
            cin>>ans[i];
        for(int i=1;i<=5;i++)
        {
            work();
            for(int j=1;j<=w;j++)
                cout<<ans[j];
            cout<<endl;
        }
        return 0; 
    }
    p1804

      p1808答案就是c(m+n,m)的后一百位.我会高精度!但是除法不太行,因为求不了逆元.

      考虑在班里求组合数,先把分子分母写出来,然后上下消去公因数,然后再把分子乘起来的操作.类比一下,先求出1到m+n的质数并且存起来,对于需要求的组合数,只需要记录m+1到m+n和2到n的数的质因数还剩下多少,再用高精度乘起来.高精度乘单精度还是很好写的.

      这道是我上午写的最简单的题了.

    long long num[100000],sum[100010],k;
    long long ans[30];
    bool zhi(int x)
    {
        for(int i=sqrt(x*1.0);i>=2;i--)
            if(x%i==0)
                return 0;
        return 1;
    }
    void Add(long long  x)
    {
        for(int i=1;x>=num[i]&&i<=k;i++)
        {
            while(x%num[i]==0)
                x=x/num[i],sum[i]++;
        }
        return ;
    }
    void Minus(long long x)
    {
        for(int i=1;x>=num[i]&&i<=k;i++)
        {
            while(x%num[i]==0)
                x=x/num[i],sum[i]--;
        }
        return ;
    }
    void mul(long long x)
    {
        for(int i=1;i<=20;i++)
            ans[i]=ans[i]*x;
        for(int i=1;i<=20;i++)
            ans[i+1]+=ans[i]/100000,ans[i]=ans[i]%100000;
        return ;
    }
    int main()
    {
        int m=read(),n=read();
        if(m<n)
            swap(m,n);
        for(int i=2;i<=m+n;i++)
            if(zhi(i))
                k++,num[k]=i;
        for(int i=m+n;i>m;i--)
            Add(i);
        for(int i=2;i<=n;i++)
            Minus(i); 
        ans[1]=1;
        for(int i=1;i<=k;i++)
            while(sum[i])
                mul(num[i]),sum[i]--;
        for(int i=20;i;i--)
        {
            long long t=10000;
            while(t&&ans[i]/t==0)
                cout<<0,t=t/10;
            if(ans[i])
                cout<<ans[i];
            if(i%2)
                cout<<endl;
        }
        return 0;
    }
    p1806

      然后中午学弟问了我一道统计数字:

    某次科研调查时得到了n(n<=200000)个自然数,每个数均不超过1500000000(1.5*10^9)。已知不相同的数不超过10000个,现在需要统计这些自然数各自出现的次数,并按照自然数从小到大的顺序输出统计结果。

      他们还没学sort,桶排序也不行,这可咋办呢?

      我一拍大腿,我会map!

      作为map的忠实粉丝,即使map常数很大,但因为它的简单易行(与数组相似),我一直很喜欢用它艹一些题.

      map<long long,int>sum;来统计每个数的数量.然后用一个迭代器便利map里的元素输出即可.

    map<long long,int> a;
    long long n,x,maxx;
    int main()
    {
        n=read();
        while(n)
            a[read()]++,n--;
        map<long long,int>::reverse_iterator   iter;
        for(iter = a.rend(),iter--; iter != a.rbegin(); iter--)
        {
            write(iter->first);
            putchar(32);
            write(iter->second);
            putchar(10);
        } 
        write(iter->first);
        putchar(32);
        write(iter->second);     
        return 0;
    } 
    #92统计数字

      最后用map艹翻了一众sort,.

       

  • 相关阅读:
    一行语句让你的浏览器变成记事本
    为啥只有IPv4和IPv6,没有IPv5呢?
    在线C++编译器
    怎么让Visual Studiot在遇到一个project编译错误时停止编译其它project
    C#的继承类中static constructor的调用问题
    C#中静态构造函数导致的一个deadlock
    一个C++的轻量级的logger实现
    一个免费轻量的Mathematica替代Mathics
    实时交通路况
    构建WAP邮件发送服务器
  • 原文地址:https://www.cnblogs.com/qywyt/p/13517069.html
Copyright © 2011-2022 走看看