POJ-1850-Code-組合數學
阿新 • • 發佈:2019-02-03
http://poj.org/problem?id=1850
本題其實並不難。。。自己給自己嚇到了。。看了複雜的題解。。。
和3252的思路一樣,要求當前字串的位置,設當前長度為x
1、先求 len<x的字串數量,
2、再求len==x,比當前字串小的數量
顯然,要求長度為k,的字串,滿足嚴格增序的種類,就是 C(26,k)【直接從a,b,c.....z選k個】
把 長度小於x的 所有i,累加C【26】【i】;// 得到第一部分值
那麼對於第二部分,
同長度下,如:bceg
首字母為b, 那麼顯然之前可以有 以a開頭的,剩下部分長度為3的所有字串,
即: 要加上 所有 s[0]之前,‘a’之後的字母開頭的,長度為x-1的字串
其餘非首字母
如e, 顯然此時要列舉的字串前兩位是bc, 那麼我們只需要第三位 大於c且小於e,剩餘部分隨意
也就是 從s[i-1]+1到s[i]-1,中 的 某個字母作為開頭,剩下長度為len-i-1的字串【任意選】
至於這個任意選也很好處理,如果 開頭的是c,那麼任意選就是從 26-3個字母裡面選擇 len-i-1個
C【26-3】【len-i-1】
#include <cstdio> #include <cmath> #include <cstring> #include <string> #include <algorithm> #include <queue> #include <map> #include <set> #include <stack> #include <iostream> using namespace std; __int64 inf=15; double eps=0.000001; __int64 n,m; char tm[15]; __int64 cc[100][100]; void pre() { __int64 i,j; for (i=0;i<=40;i++) cc[i][0]=1; for (i=1;i<=40;i++) for(j=1;j<=40;j++) cc[i][j]=(cc[i-1][j-1]+cc[i-1][j]); } int check(char *s,int len) { for (int i=1;i<len;i++) { if (s[i]<=s[i-1]) return 0; } return 1; } int main() { pre(); scanf("%s",tm); int len=strlen(tm); int ret=check(tm,len); if (ret==0) { printf("0\n"); return 0;} __int64 sum=0,i,j; for (i=1;i<len;i++)//累計所有長度小於len的字串個數 sum+=cc[26][i]; //接下來算長度等於len的字串個數 if (tm[0]>'a') { __int64 tmp=0; for (i=1;i<=tm[0]-'a'-1+1;i++) //tm[0]-'a'+1得到該字母對應數字,減一表示按照嚴格遞增 tmp+=cc[26-i][len-1]; sum+=tmp; } for (i=1;i<len;i++) { if (tm[i]-1-tm[i-1]>0) { __int64 tmp=0; for (j=tm[i-1]-'a'+1+1;j<=tm[i]-'a'+1-1;j++) //tm[i-1]-'a'+1得到該字母對應數字,加一表示按照嚴格遞增,不與i-1個字元重複,其他同理 tmp+=cc[26-j][len-i-1]; sum+= tmp; } } printf("%I64d\n",sum+1); return 0; }