poj 1850 组合计数

题意:给一个字符串 S,长度<=10,其中的字母按升序排列。长度小的字符串比大的字符串靠前,长度相同按字典序排列,问 S 排第几个。

a - 1 
b - 2 
... 
z - 26 
ab - 27 
... 
az - 51 
bc - 52 
... 
vwxyz - 83681

分析:字母按升序排列,则选出若干字母,其排列唯一。先求长度len,比它短的字符串有C(26,1) + C(26,2) +...+C(26,len-1) 个。

对于长度相同的字符串,设S=“ b d f h t ”,则前四位和 S 相同,最后一位小于 't' 并且大于 'h' 的有C('z'-'h',1) - C('z'-'t'+1,1)种情况。

前三位和S相同,后两位小于S的有C('z'-'f', 2) - C('z'-'h'+1, 2)种。

......

 

 

const int maxn = 27;
LL a[maxn][maxn];

void init(){
    FOR(i,0,maxn) {
        a[i][0]=1; a[i][1]=i;
        FOE(j,2,i) a[i][j] = a[i-1][j] + a[i-1][j-1];
    }
}

int main(){
    #ifndef ONLINE_JUDGE
    //freopen("in.txt","r",stdin);
    //freopen("out.txt","w",stdout);
    #endif

    init();

    string s;
    cin>>s;
    int l = s.length();
    FOR(i,0,l-1) if(s[i]>=s[i+1]) {cout<<0<<endl;return 0;}
    LL cnt = 0;

    FOR(i,1,l) cnt+=a[26][i];
    FOR(i,1,l){
        char c = s[l-i], c1 = s[l-i-1];
        cnt += a['z'-c1][i] - a['z'-c+1][i];
    }
    cnt += a[26][l] - a['z'-s[0]+1][l];
    
    cout<<cnt+1<<endl;
    return 0;
}

 

posted @ 2013-05-01 19:42  心向往之  阅读(127)  评论(0编辑  收藏  举报