Baby's Blocks Gym - 101518D 组合排列

参考:https://vjudge.net/problem/Gym-101518D

D. Baby’s Blocks
Mikey is playing with his favorite toy blocks, each depicting one letter of the alphabet. He is
trying to make words using all his blocks, but as he does not know valid words from invalid
ones, he goes by all possible orderings of the letters in alphabetical order and asks Albert, his
genius brother, if the word he made is a valid one. Mikey can make one word (including asking
a question and getting an answer) every sixty seconds, and he never makes the same word twice.
Albert is delighted about Mikey’s activity, but would rather not teach Mikey certain words.
Help Albert by predicting when Mikey will start making a certain forbidden word, so he can set
the alarm clock indicating Mikey’s bedtime to just before this moment.
Input
On the first line of the input is a positive integer, the number of test cases. Then for each test
case:
• A line containing the forbidden word to look for, consisting of at most 20 upper case
characters. This word can be formed exactly using all of Mikey’s blocks.
Output
For each test case:
• One line containing the number of minutes it will take until the forbidden word is reached,
assuming Mikey has just started making the first possible word.
Example
Input Output
4
ABC
FSCK
OMGWFTBBQ
BANANA
0
10
112293
34

题意:求当前串是字母重排后第几的串(不可重复的)。

#include<bits/stdc++.h>
using namespace std;
#define LL long long

int a[30],b[30];
char s[30];
LL fac[30];
void solve(){
    scanf("%s",s+1);
    int len=strlen(s+1);
    memset(b,0,sizeof(b));
    fac[0]=1;
    for(int i=1;i<=len;++i){
        a[i]=s[i]-'A';
        b[a[i]]++;
        fac[i]=fac[i-1]*i;
    }
    LL ans=0;
    for(int i=1;i<=len;++i){
        LL tmp=0;
        for(int j=0;j<a[i];++j){
            if(!b[j])continue;
            b[j]--;
            tmp=fac[len-i];
            for(int k=0;k<26;++k){
                tmp/=fac[b[k]];
            }
            b[j]++;
            ans+=tmp;
        }
        b[a[i]]--;
    }
    printf("%lld\n",ans);
}
int main(){
    int T;scanf("%d",&T);
    while(T--){
        solve();
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值