zoukankan      html  css  js  c++  java
  • poj1850和poj1496(组合数)

    题目意思:给出一串字符串问按照文中的序号排,序号是多少。

    思路:先计算出n位字符,一共有多少种情况,再减去比这个字符大的情况种数。

    主要步骤一:

    长度为一的字符串有26种(a,b,c,...,z)   C(26,1)

    长度为二的字符串有:

        以a开头的25种(ab,ac,ad,...,az)  C(25,1)

        以b开头的24种(bc,bd,...,bz)      C(24,1)

        ...                                                 ...

        以y开头的有1种,yz       C(1,1)

    一共 C(25,1)+C(24,1)+...+C(1,1)=1+2+3+..+25=25*26/2=C(26,2)

    其实这里有一个重要的组合数公式:

    长度为三的自然有C(26,3)种

    那只要一个循环就可以将每一位一共的情况计算出来。

    主要步骤二:

    减去每一位比它大的字符串。这里可以想象成拿小球了。

    例如: abc     

    计算第一位  abc     比a大的字符有25个,只要从中选三个字符组合就比它大  所以是C(25,3)

    计算第二位 abc      比b大的字符有24个,只要从中选两个构成(axx)就比它大,所以是C(24,2)

    计算第二位 abc      比c大的字符有23个,只要从中选一个构成(abx)就比它大,所以是C(23,1)

    这样就计算出来序号了。但是   注意不可法的情况输出0

    下面是poj1850的代码:

    #include<iostream>
    #include<algorithm>
    #include<cstdio>
    #include<cstring>
    #define inf 0x3f3f3f3f
    using namespace std;
    typedef long long ll;
    int c[30][30];
    
    void init()//组合数打表 
    {
        c[0][0]=1;
        for(int i=1;i<30;i++)
        {
            c[i][0]=1;
            for(int j=1;j<=i;j++)
                c[i][j]=c[i-1][j]+c[i-1][j-1];
        }
    }
    
    int main()
    {
        string s;
        init();
        cin>>s;
        int len=s.length();
        int res=0;
        for(int i=1;i<len;i++)//不合法情况 
        {
            if(s[i-1]>=s[i])
            {
                cout<<res<<endl;
                return 0;
            }
        }
        for(int i=1;i<=len;i++)//加每一位情况 
            res+=c[26][i];
        for(int i=0;i<len;i++)//减大于字符串的情况 
            res-=c[26-(s[i]-'a'+1)][len-i];
        cout<<res<<endl;
        return 0;
    }
    View Code

    poj1496:

    #include<iostream>
    #include<algorithm>
    #include<cstdio>
    #include<cstring>
    #define inf 0x3f3f3f3f
    using namespace std;
    typedef long long ll;
    int c[30][30];
    
    void init()
    {
        c[0][0]=1;
        for(int i=1;i<30;i++)
        {
            c[i][0]=1;
            for(int j=1;j<=i;j++)
                c[i][j]=c[i-1][j]+c[i-1][j-1];
        }
    }
    
    int main()
    {
        string s;
        init();
        while(cin>>s)
        {
            int len=s.length();
            int res=0,flag=0;
            for(int i=1;i<len;i++)
            {
                if(s[i-1]>=s[i])
                {
                    cout<<res<<endl;
                    flag=1;
                }
            }
            if(flag)
                continue;
            for(int i=1;i<=len;i++)
                res+=c[26][i];
            for(int i=0;i<len;i++)
                res-=c[26-(s[i]-'a'+1)][len-i];
            cout<<res<<endl;
        }
        return 0;
    }
    View Code
  • 相关阅读:
    TCP/IP的确认号,序列号和超时重传的学习笔记
    Linux进程的虚拟内存
    Linux内存:物理内存管理概述
    Linux进程: task_struct结构体成员
    Linux进程:管理和调度
    Golang基础(8):go interface接口
    技术管理:团队建设
    从分布式一致性谈到CAP理论、BASE理论
    技术管理:项目管理概要
    [译]深入 NGINX: 为性能和扩展所做之设计
  • 原文地址:https://www.cnblogs.com/xiongtao/p/10895890.html
Copyright © 2011-2022 走看看