洛谷P1246编码问题-排列组合,分类讨论

Posted ckxkexing

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了洛谷P1246编码问题-排列组合,分类讨论相关的知识,希望对你有一定的参考价值。

编码问题

题意就是a,b,c.....ab.....编码,给你一个字符串,输出这是第几个;

这里可以用暴力枚举,但也可以用组合数学的高超知识;

 

既然这样我就说一下排列组合的方法,如果要弄一个 各位数字递增的三位数,只需要在一个有序数列里面取三个数字,此时就无需关注顺序,因为顺序只能是升序的。比如0 1 2 3 4 5 6 7 8 9。取得9 5 8 那么他的顺序就只能是589。总数就是C(x,y),x代表位数,y代表可供选择的数的长度,

就像例子中是c(3,10)。对于字母排列,道理也是一样。只需要注意一下y的大小,然后从左到右一步一步推下去就好。

#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
#include <string>

using namespace std;
int f[27][100];
int d[7];
string str;

int main(){
    ios::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);
    cin>>str;
    f[0][0] = 1;
    for(int i=1;i<=26;i++)                //用打表的方式做组合C的计算
    {
        for(int j=0;j<=100;j++)
            f[i][j] = f[i-1][j-1] + f[i-1][j];
    }
    int l = str.length();
    for(int i=0; i<l; i++)
    {
        d[i] = str[i] -‘a‘ +1;
        if(i>0 && d[i]<=d[i-1]){cout<<0<<endl;return 0;}    
    }
    if(l==0){cout<<0<<endl;return 0;}
    if(l==1){cout<<d[0]<<endl;return 0;}
    //累加长度小于L的可能性;??
    int sum = 0;
    for(int i=1; i<l; i++)
    {
        sum+= f[26][i];//i 代表个数;
    }
    //下面是求l位数的前面; 如:BDF 先计数A**的个数 再到BC*的个数 再BD
    for(int i=0;i<l-1;i++)
    {
        if(i==0)
        {
            for(int j=1; j<d[i]; j++)
                sum+=f[26-j][l-i-1];
        }
        else 
        {
            for(int j=d[i-1]+1; j<d[i]; j++)
            {
                sum+=f[26-j][l-i-1];
            }
        }
    }
    sum+=d[l-1]-d[l-2];   //比如BDE到BDF有2个,这个需要加上去。
    cout<<sum<<endl;
    return 0;
}

 

以上是关于洛谷P1246编码问题-排列组合,分类讨论的主要内容,如果未能解决你的问题,请参考以下文章

itertools 排列组合

洛谷P1157 组合的输出

●洛谷P2606 [ZJOI2010]排列计数

洛谷 P1157 组合的输出

排列和组合的求解

一个排列组合的题:把n个不同的球放入m个不同的盒子里且盒子都不能空,有多少种方法?谢谢