搜索和组合数学P1246 编码

  题目链接P1246 编码

博客园食用更佳

题意简述

  • 要求给字符串按照规定编号,字符串长度小于等于 6 6 6
  • 能编号的字符串的字母一定是递增的,规定:
    • a → 1 \mathbf{a}\rightarrow 1 a1

    • b → 2 \mathbf{b}\rightarrow 2 b2

      ⋯ \cdots

    • z → 26 \mathbf{z}\rightarrow 26 z26

    • a b → 27 \mathbf{ab}\rightarrow 27 ab27

    • 最后一个编号 u v w x y z → 313911 \mathbf{uvwxyz}\rightarrow313911 uvwxyz313911

  • 如果给出的字符串字母不递增,则输出 0 0 0 ,否则输出对应编号。

暴力枚举

  首先数据范围很小。先简单算一下,用组合数计算出每一个长度能编号的字符串数目。

  • 长度为 1 1 1 能编号的字符串数目为 C 26 1 = 26 C_{26}^1 = 26 C261=26
  • 长度为 2 2 2 能编号的字符串数目为 C 26 2 = 325 C_{26}^2 = 325 C262=325

  把 6 6 6 个组合数加起来编号就是 313911 313911 313911 ,即最后一个字符串 u v w x y z \mathbf{uvwxyz} uvwxyz 的编号,完全可以枚举每一个可以编号的字符串,找到匹配的就输出编号即可,否则输出 0 0 0

C o d e : Code: Code:

#include <bits/stdc++.h>
#define FOR(i,a,b) for(int i = a;i <= b;i++)
using namespace std;
char s[10],test[10];//s记录询问的字符串,test记录尝试的字符串
int n,id;  //n记录询问字符串长度,id为编号

//last记录前一个字母,step记录递归层数,枚举下一位
void dfs(char last, int step){
    if(!step) return;
    for (char i = last + 1; i <= 'z'; i++) {
        test[step] = i;
        if(step == 1) {
            id++;     //枚举到最后一位编号才加一
            int flag = 1;
            FOR(j,1,n) if(s[j] != test[n - j + 1]) flag = 0; //逐位比对,注意test是逆着记录的
            if(flag) {cout << id;exit(0);}
        }
        dfs(i,step-1);
    }
}

signed main(){
    scanf("%s", s + 1);
    n = strlen(s + 1);
    FOR(i,1,n)
        dfs('a'-1,i);

    cout<<0;  //在dfs中未找到,说明字符串不满足要求
    return 0;
}

组合数学

  这题如果数据量较大可以用组合数学解决。我们先算出长度为 1 1 1~ n − 1 n-1 n1 的能编号字符串的总数,最后再解决长度为 n n n 的字符串情况。涉及的细节可能比较多,我尽可能注释了。

C o d e : Code: Code:

#include <bits/stdc++.h>
#define FOR(i,a,b) for(int i = a;i <= b;i++)
using namespace std;
char s[10];//ch记录询问的字符串
int n,id,c[30][30];  //n记录询问字符串长度

signed main(){
    FOR(i,0,26) c[i][0] = 1;
    FOR(i,1,26) FOR(j,1,26) c[i][j] = c[i-1][j]+c[i-1][j-1];//组合数递推式,
    scanf("%s", s + 1);
    n = strlen(s + 1);
    //处理长度小于n的字符串编号
    FOR(i,1,n-1) {
        if(s[i] >= s[i+1]) {
            cout<<0;//不升序排列就直接输出0
            exit(0);
        }
        id += c[26][i]; //从26个字母中选i个,一定可以排成递增的字符串
    }
    int j ;
    FOR(i,1,n){
        //j要分情况赋值,前i-1位已固定为s[1]到s[i-1](i != 1)
        if(i == 1) j = 'a';
        else j = s[i-1]+1;

        for(;j < s[i];j++)
            id += c['z'-j][n-i]; //在第i位为字母j的情况下,后面n-i位的组合情况。
    }
    cout<<id+1; //记得加一
    return 0;
}

  还有问题的可以评论。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
C语言是一种广泛使用的编程语言,它具有高效、灵活、可移植性强等特点,被广泛应用于操作系统、嵌入式系统、数据库、编译器等领域的开发。C语言的基本语法包括变量、数据类型、运算符、控制结构(如if语句、循环语句等)、函数、指针等。在编写C程序时,需要注意变量的声明和定义、指针的使用、内存的分配与释放等问题。C语言中常用的数据结构包括: 1. 数组:一种存储同类型数据的结构,可以进行索引访问和修改。 2. 链表:一种存储不同类型数据的结构,每个节点包含数据和指向下一个节点的指针。 3. 栈:一种后进先出(LIFO)的数据结构,可以通过压入(push)和弹出(pop)操作进行数据的存储和取出。 4. 队列:一种先进先出(FIFO)的数据结构,可以通过入队(enqueue)和出队(dequeue)操作进行数据的存储和取出。 5. 树:一种存储具有父子关系的数据结构,可以通过中序遍历、前序遍历和后序遍历等方式进行数据的访问和修改。 6. 图:一种存储具有节点和边关系的数据结构,可以通过广度优先搜索、深度优先搜索等方式进行数据的访问和修改。 这些数据结构在C语言中都有相应的实现方式,可以应用于各种不同的场景。C语言中的各种数据结构都有其优缺点,下面列举一些常见的数据结构的优缺点: 数组: 优点:访问和修改元素的速度非常快,适用于需要频繁读取和修改数据的场合。 缺点:数组的长度是固定的,不适合存储大小不固定的动态数据,另外数组在内存中是连续分配的,当数组较大时可能会导致内存碎片化。 链表: 优点:可以方便地插入和删除元素,适用于需要频繁插入和删除数据的场合。 缺点:访问和修改元素的速度相对较慢,因为需要遍历链表找到指定的节点。 栈: 优点:后进先出(LIFO)的特性使得栈在处理递归和括号匹配等问题时非常方便。 缺点:栈的空间有限,当数据量较大时可能会导致栈溢出。 队列: 优点:先进先出(FIFO)的特性使得

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

ailanxier

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值