洛谷P1246編碼問題-排列組合,分類討論
阿新 • • 發佈:2018-02-10
知識 names 合數 .... ostream 排列 大小 post new
編碼問題
題意就是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編碼問題-排列組合,分類討論