HDU - 5651 xiaoxin juju needs help(Java JS Python C C++)

题目来源

Problem - 5651 (hdu.edu.cn)

题目描述

众所周知,小新是一位才华横溢的程序员。当他还是小学六年级的学生时,他就知道回文字符串了。

今年夏天,他在腾讯实习。一天,他的领导来找小新帮忙。他的领导给了他一个字符串,他想让小新为他生成回文字符串。

一旦小新生成一个不同的回文串,他的领导就会给他一个西瓜糖。

问:小新的领导需要买多少糖果?

输入描述

这个问题有多个测试用例。

第一行,包含单个整数 T,它表示测试用例的数量。

  • T ≤ 20

对于每个测试用例,有一行,包含字符串S。

  • 1 ≤ length(S) ≤ 1000

输出描述

对于每个测试用例,打印一个整数,这是小新的领导需要购买的西瓜糖的数量,模取1,000,000,007。

用例

输入3
aa
aabb
a
输出1
2
1

题目解析

本题的解题思路其实很简单。

给定一个字符串s,我们可以任意重排s内字符的顺序,如果新串是回文串,则结果数量+1。

比如:s = "aabb",重排后有:"baab","abba" 两种回文串。

那么,我们该如何求解一个字符串重排后可得的回文串数量呢?

思路很简单:

首先,我们需要统计字符串s中各个字符的出现次数

然后,检查“出现次数为奇数次”的字符的数量,如果这个数量超过1,那么字符串s就无法重排出回文串,因为回文串是左右对称的,即可以在中间位置一分为二,比如:

  • 没有“出现次数为奇数次”的字符

  • 有一个“出现次数为奇数次”的字符


  • 但是如果有一个以上的“出现次数为奇数次”的字符时,某一边就会多出无法对称的字符

因此,如果统计到的“出现次数为奇数次”的字符数量>1,则对应字符串s无法重排出回文串。

反之,如果统计到的“出现次数为奇数次”的字符数量 ≤ 1,则对应字符串s可以重排出回文串。但是如果计算可以重排的回文串数量呢?

比如s = "aabb",那么有如下两种情况:

由于回文串是左右对称的,因此,当我们求出回文串的左半部分时,其右半部分也自然确定了。

比如,回文串左半部分是"ab",那么回文串右半部分必然是"ba"。

因此,我们可以将之前统计的字符串s的各个字符数量除以2,得到回文串左半部分的各字符数量,然后求回文串左半部分的(不重复的)全排列数量,即为回文串的数量。

比如 s = "aabb",其中统计结果 a字符有2个,b字符有2个,

那么用于组成回文串左半部分的字符数量为:a字符1个,b字符1个。

而1个a字符,一个b字符,可以组成的全排列有"ab"和"ba"两种。即对应的回文串有2种。

另外,还有一个需要注意的是,如果s = "abbba",其中统计结果:a字符有2个,b字符有3个

那么用于组成回文串左半部分的字符数量为:a字符1个,b字符1.5个?

其实,此时“出现奇数次”的b字符,可以抠出来一个b固定为回文串的中间字符,这个作为中间字符的b既不属于左半部分,也不属于右半部分。

因此,我们可以理解为:回文串左半部分字符数量为:a字符1个,b字符1个(即:3整除2的结果)

那么本题的问题又可以变为:求一组元素的不重复的全排列数量。

假设有n个数,则这n个数的全排列数量即为:n!

比如 [1,2,3] 的全排列有 3!个,分别为:

  • 123
  • 132
  • 213
  • 231
  • 312
  • 321

那么这n个数如果存在重复元素,比如 [1,2,2] 的全排列有:

  • 122
  • 122
  • 212
  • 221
  • 212
  • 221

其中画删除线的都是重复的全排列,那么此时该如何求解不重复的全排列数量呢?

假设有 n 个字符,分为 k 种,

第1种有n1个相同字符,第2种有n2个相同字符,...,第k种有nk个相同字符,

存在关系:n1+n2+...+nk == n

那么,此时不重复全排列数量为:

n! / n1! / n2! / ... / nk! 

比如 [1,2,2] 的有两种字符:字符1有1个,字符2有2个,那么其不重复的全排列数量为:

3! / 1! / 2!

以上就是本题的基础解题思路,总结一下就是:

  • 首先,统计字符串s中各个字符的出现次数
  • 然后,检查“出现次数为奇数次”的字符的数量,如果这个数量超过1,则字符串s无法重排出回文串,即结果为0,否则继续下一步
  • 之后,将各个字符数量整除2,得到回文串左半部分各字符数量
  • 最后,基于回文串左半部分各字符数量求不重复的全排列数量,即为字符串s可以重排出的回文串数量

题目输出描述中说:需要对输出结果值取模1,000,000,007。因此本题的结果实际为:

(n! / n1! / n2! / ... / nk! )% 1000000007

但是,这里面有一个问题,那就是,字符串s长度最大1000,也就是说回文串左半部分字符总数最大可以n=500,因此按照上面策略,我们必然要求解 500!,这是一个极其庞大的数,计算过程中肯定会long溢出。

当然,如果你的编程语言支持大数的四则运算的话,可以不用担心这个问题,比如Java的BigInteger类型,JS的BigInt类型。

但是其他语言,比如C/C++语言不支持大数的四则运算,Python不支持大数除法(可以支持大数的加法、减法,乘法)。

因此我们依旧需要考虑如果避免整型溢出。


这题为什么要我们将结果值对1000000007,即1e9 + 7取模呢?

因为这涉及到一个知识点:除法取模

算法竞赛6.1-模运算_哔哩哔哩_bilibili

而除法取模又涉及到了:乘法逆元

【C++/算法】乘法逆元详解_哔哩哔哩_bilibili

而乘法逆元的求解又涉及到了:费马小定理

数论:费马小定理_哔哩哔哩_bilibili

由费马小定理公式,类比为,乘法逆元公式,我们又需要基于:快速幂算法来求解逆元

【C++/算法】快速幂算法详解_哔哩哔哩_bilibili

Java算法源码

解法一:基于BigInteger类型
import java.math.BigInteger;
import java.util.Scanner;

public class Main {
    static BigInteger[] fact = new BigInteger[501];

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);

        // 初始化1~500的阶乘
        initFact();

        // 输入获取
        int t = Integer.parseInt(sc.nextLine());
        for (int i = 0; i < t; i++) {
            String s = sc.nextLine();
            // 核心代码调用
            System.out.println(solution(s));
        }
    }

    public static void initFact() {
        fact[0] = new BigInteger("1");

        for (int i = 1; i <= 500; i++) {
            fact[i] = new BigInteger(i + "").multiply(fact[i - 1]);
        }
    }

    public static String solution(String s) {
        // 求s串每个字符c的数量
        int[] count = new int[26];
        for (int i = 0; i < s.length(); i++) {
            char c = s.charAt(i);
            count[c - 'a']++;
        }

        // "出现次数为奇数次的"字符的数量
        int odd = 0;
        for (int i = 0; i < 26; i++) {
            if (count[i] % 2 != 0) {
                odd++;
            }

            count[i] /= 2; // 只保留一半字符数量, 后续只需要用到回文串的左半部分,即一半的字符
        }

        // 如果"出现次数为奇数次的"字符的数量不止1个,则s串无法重组出回文串
        if (odd > 1) {
            return "0";
        }

        // 不重复的全排列数
        BigInteger ans = fact[s.length() / 2];
        for (int i = 0; i < 26; i++) {
            ans = ans.divide(fact[count[i]]);
        }

        return ans.mod(new BigInteger("1000000007")).toString();
    }
}
解法二:除法取模,乘法逆元,费马小定理,快速幂
import java.util.Scanner;

public class Main {
    static final long mod = 1000000007;
    static long[] fact = new long[501];

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);

        // 初始化1~500的阶乘
        initFact();

        // 输入获取
        int t = Integer.parseInt(sc.nextLine());
        for (int i = 0; i < t; i++) {
            String s = sc.nextLine();
            // 核心代码调用
            System.out.println(solution(s));
        }
    }

    public static void initFact() {
        fact[0] = 1;

        for (int i = 1; i <= 500; i++) {
            fact[i] = i * fact[i - 1] % mod;
        }
    }

    public static long solution(String s) {
        // 求s串每个字符c的数量
        int[] count = new int[26];
        for (int i = 0; i < s.length(); i++) {
            char c = s.charAt(i);
            count[c - 'a']++;
        }

        // "出现次数为奇数次的"字符的数量
        int odd = 0;
        for (int i = 0; i < 26; i++) {
            if (count[i] % 2 != 0) {
                odd++;
            }

            count[i] /= 2; // 只保留一半字符数量, 后续只需要用到回文串的左半部分,即一半的字符即可
        }

        // 如果"出现次数为奇数次的"字符的数量不止1个,则s串无法重组出回文串
        if (odd > 1) {
            return 0;
        }

        // 不重复的全排列数
        long ans = fact[s.length() / 2];
        for (int i = 0; i < 26; i++) {
            // 假设 x == fact[count[i] / 2]
            // ans / x % mod
            // 等价于
            // ans * x的乘法逆元 % mod
            // 而x的乘法逆元为 fast_pow(x, mod-2, mod)
            ans = ans * fast_pow(fact[count[i]], mod - 2, mod) % mod;
        }

        return ans;
    }

    // 快速幂算法:用于求解 (a^b) % mod 的结果
    public static long fast_pow(long a, long b, long mod) {
        long ans = 1; // 记录结果

        a %= mod;

        // 快速幂算法是为了高效计算a^b, 举例
        // 3^5
        //  = 3 * 3^4
        //  = 3 * 9^2
        //  = 3 * 81^1
        //  = 3 * 81 * 81^0
        // 这个过程中如果发现b为奇数,则析出一个底a作为乘数, 实现 b-=1
        // 这个过程中如果发现b为偶数,则底a进行平方运算,实现 b/=2
        // 这个算法求解a^b的时间复杂度为O(log2(b)), 相较于O(b)算法十分高效
        while (b != 0) {
            if (b % 2 == 1) { // 位运算优化: if(b&1 == 1)
                // 3^5 析出来一个3后, 变为 3 * 3^4, 将b值从奇数变为偶数
                // 下面将析出的来3合入结果ans中, 则剩余3^4
                ans = (ans * a) % mod;
                // b -= 1; // 可以不用此步, 因为后面b会整除2
            }

            // 3^4 变为 9^2
            a = (a * a) % mod; // 底数3 变为 9
            b /= 2; // 幂4 变为 2  // 位运算优化: b>>=1
        }

        return ans;
    }
}

JS算法源码

解法一:基于BigInt类型
const rl = require("readline").createInterface({ input: process.stdin });
var iter = rl[Symbol.asyncIterator]();
const readline = async () => (await iter.next()).value;

let fact;

void (async function () {
  // 初始化1~500的阶乘
  initFact();

  // 输入获取
  const t = parseInt(await readline());
  for (let i = 0; i < t; i++) {
    const s = await readline();
    // 核心代码调用
    console.log(solution(s));
  }
})();

function initFact() {
  fact = new Array(501);

  fact[0] = BigInt(1);
  for (let i = 1; i <= 500; i++) {
    fact[i] = BigInt(i) * fact[i - 1];
  }
}

function solution(s) {
  // 求s串每个字符c的数量
  const count = new Array(26).fill(0);
  for (let i = 0; i < s.length; i++) {
    count[s.charCodeAt(i) - 97]++;
  }

  // "出现次数为奇数次的"字符的数量
  let odd = 0;
  for (let i = 0; i < 26; i++) {
    if (count[i] % 2 != 0) {
      odd++;
    }

    count[i] = parseInt(count[i] / 2); // 只保留一半字符数量, 后续只需要用到回文串的左半部分,即一半的字符
  }

  // 如果"出现次数为奇数次的"字符的数量不止1个,则s串无法重组出回文串
  if (odd > 1) {
    return "0";
  }

  // 不重复的全排列数
  let ans = fact[parseInt(s.length / 2)];
  for (let i = 0; i < 26; i++) {
    ans = ans / fact[count[i]];
  }

  return (ans % BigInt("1000000007")).toString();
}
解法二:除法取模,乘法逆元,费马小定理,快速幂

JS使用快速幂的意义不大,因为JS普通数值最大只能表示(2^53)-1,如果超出这个数值,那么计算结果就会不准确。

而求解快速幂的过程中,是非常有可能产生一个大于(2^53)-1的值的,JS貌似没有像Java一样做long * long % long 这种计算过程的精度保护。

因此,JS实现快速幂的过程中,我们还是需要使用BigInt,那么又有什么意义使用快速幂呢?

const rl = require("readline").createInterface({ input: process.stdin });
var iter = rl[Symbol.asyncIterator]();
const readline = async () => (await iter.next()).value;

const mod = BigInt(1000000007);
const fact = new Array(501);

void (async function () {
  // 初始化1~500的阶乘
  initFact();

  // 输入获取
  const t = parseInt(await readline());
  for (let i = 0; i < t; i++) {
    const s = await readline();
    // 核心代码调用
    console.log(solution(s));
  }
})();

function initFact() {
  fact[0] = 1n;
  for (let i = 1; i <= 500; i++) {
    fact[i] = (BigInt(i) * fact[i - 1]) % mod;
  }
}

function solution(s) {
  // 求s串每个字符c的数量
  const count = new Array(26).fill(0);
  for (let i = 0; i < s.length; i++) {
    count[s.charCodeAt(i) - 97]++;
  }

  // "出现次数为奇数次的"字符的数量
  let odd = 0;
  for (let i = 0; i < 26; i++) {
    if (count[i] % 2 != 0) {
      odd++;
    }

    count[i] >>= 1; // 只保留一半字符数量, 后续只需要用到回文串的左半部分,即一半的字符
  }

  // 如果"出现次数为奇数次的"字符的数量不止1个,则s串无法重组出回文串
  if (odd > 1) {
    return 0;
  }

  // 不重复的全排列数
  let ans = fact[s.length >> 1];
  for (let i = 0; i < 26; i++) {
    // 假设 x == fact[count[i] / 2]
    // ans / x % mod
    // 等价于
    // ans * x的乘法逆元 % mod
    // 而x的乘法逆元为 fast_pow(x, mod-2, mod)
    ans = (ans * fast_pow(fact[count[i]], mod - 2n, mod)) % mod;
  }

  return ans.toString();
}

// 快速幂算法:用于求解 (a^b) % mod 的结果
function fast_pow(a, b, mod) {
  let ans = 1n; // 记录结果

  a %= mod;

  // 快速幂算法是为了高效计算a^b, 举例
  // 3^5
  //  = 3 * 3^4
  //  = 3 * 9^2
  //  = 3 * 81^1
  //  = 3 * 81 * 81^0
  // 这个过程中如果发现b为奇数,则析出一个底a作为乘数, 实现 b-=1
  // 这个过程中如果发现b为偶数,则底a进行平方运算,实现 b/=2
  // 这个算法求解a^b的时间复杂度为O(log2(b)), 相较于O(b)算法十分高效
  while (b != 0n) {
    if (b % 2n == 1n) {
      // 3^5 析出来一个3后, 变为 3 * 3^4, 将b值从奇数变为偶数
      // 下面将析出的来3合入结果ans中, 则剩余3^4
      ans = (ans * a) % mod;
      b -= 1n;
    }

    // 3^4 变为 9^2
    a = (a * a) % mod; // 底数3 变为 9
    b /= 2n; // 幂4 变为 2
  }

  return ans;
}

Python算法源码

解法一:除法取模,乘法逆元,费马小定理,快速幂
# 全局变量
fact = [0] * 501
mod = 1000000007


def initFact():
    fact[0] = 1
    for i in range(1, 501):
        fact[i] = i * fact[i - 1] % mod


# 快速幂算法:用于求解 (a^b) % mod 的结果
def fast_pow(a, b):
    ans = 1  # 记录结果

    a %= mod

    # 快速幂算法是为了高效计算a^b, 举例
    # 3 ^ 5
    # = 3 * 3 ^ 4
    # = 3 * 9 ^ 2
    # = 3 * 81 ^ 1
    # = 3 * 81 * 81 ^ 0
    # 这个过程中如果发现b为奇数,则析出一个底a作为乘数, 实现 b -= 1
    # 这个过程中如果发现b为偶数,则底a进行平方运算,实现 b /= 2
    # 这个算法求解a ^ b的时间复杂度为O(log2(b)), 相较于O(b)算法十分高效
    while b != 0:
        if b % 2 == 1:  # 位运算优化: if(b&1 == 1)
            # 3^5 析出来一个3后, 变为 3 * 3^4, 将b值从奇数变为偶数
            # 下面将析出的来3合入结果ans中, 则剩余3^4
            ans = ans * a % mod
            # b -= 1; # 可以不用此步, 因为后面b会整除2

        # 3^4 变为 9^2
        a = a * a % mod  # 底数3 变为 9
        b //= 2  # 幂4 变为 2  # 位运算优化: b>>=1

    return ans


def solution(s):
    # 求s串每个字符c的数量
    count = [0] * 26
    for i in range(len(s)):
        count[ord(s[i]) - 97] += 1

    # "出现次数为奇数次的"字符的数量
    odd = 0
    for i in range(26):
        if count[i] % 2 != 0:
            odd += 1

        count[i] //= 2  # 只保留一半字符数量, 后续只需要用到回文串的左半部分,即一半的字符即可

    # 如果"出现次数为奇数次的"字符的数量不止1个,则s串无法重组出回文串
    if odd > 1:
        return 0

    # 不重复的全排列数
    ans = fact[len(s) // 2]
    for i in range(26):
        # 假设 x == fact[count[i] / 2]
        # ans / x % mod
        # 等价于
        # ans * x的乘法逆元 % mod
        # 而x的乘法逆元为 fast_pow(x, mod-2, mod)
        ans = ans * fast_pow(fact[count[i]], mod - 2) % mod

    return ans


if __name__ == '__main__':
    # 初始化1~500的阶乘
    initFact()

    # 输入获取
    t = int(input())
    for _ in range(t):
        # 核心代码调用
        print(solution(input()))
解法二:使用内置函数pow代替快速幂
# 全局变量
fact = [0] * 501
mod = 1000000007


def initFact():
    fact[0] = 1
    for i in range(1, 501):
        fact[i] = i * fact[i - 1] % mod


def solution(s):
    # 求s串每个字符c的数量
    count = [0] * 26
    for i in range(len(s)):
        count[ord(s[i]) - 97] += 1

    # "出现次数为奇数次的"字符的数量
    odd = 0
    for i in range(26):
        if count[i] % 2 != 0:
            odd += 1

        count[i] //= 2  # 只保留一半字符数量, 后续只需要用到回文串的左半部分,即一半的字符即可

    # 如果"出现次数为奇数次的"字符的数量不止1个,则s串无法重组出回文串
    if odd > 1:
        return 0

    # 不重复的全排列数
    ans = fact[len(s) // 2]
    for i in range(26):
        # 假设 x == fact[count[i] / 2]
        # ans / x % mod
        # 等价于
        # ans * x的乘法逆元 % mod
        # 而x的乘法逆元为 fast_pow(x, mod-2, mod)
        ans = ans * pow(fact[count[i]], mod - 2, mod) % mod

    return ans


if __name__ == '__main__':
    # 初始化1~500的阶乘
    initFact()

    # 输入获取
    t = int(input())
    for _ in range(t):
        # 核心代码调用
        print(solution(input()))

C算法源码

除法取模,乘法逆元,费马小定理,快速幂

#include <stdio.h>
#include <string.h>

#define MAX_LEN 1001
#define MOD 1000000007

long long fact[501] = {0};

void initFact() {
    fact[0] = 1;

    for (int i = 1; i <= 500; i++) {
        fact[i] = i * fact[i - 1] % MOD;
    }
}

// 快速幂算法:用于求解 (a^b) % mod 的结果
long long fast_pow(long long a, long long b) {
    long long ans = 1; // 记录结果

    a %= MOD;

    // 快速幂算法是为了高效计算a^b, 举例
    // 3^5
    //  = 3 * 3^4
    //  = 3 * 9^2
    //  = 3 * 81^1
    //  = 3 * 81 * 81^0
    // 这个过程中如果发现b为奇数,则析出一个底a作为乘数, 实现 b-=1
    // 这个过程中如果发现b为偶数,则底a进行平方运算,实现 b/=2
    // 这个算法求解a^b的时间复杂度为O(log2(b)), 相较于O(b)算法十分高效
    while (b != 0) {
        if (b % 2 == 1) { // 位运算优化: if(b&1 == 1)
            // 3^5 析出来一个3后, 变为 3 * 3^4, 将b值从奇数变为偶数
            // 下面将析出的来3合入结果ans中, 则剩余3^4
            ans = ans * a % MOD;
            // b -= 1; // 可以不用此步, 因为后面b会整除2
        }

        // 3^4 变为 9^2
        a = a * a % MOD; // 底数3 变为 9
        b /= 2; // 幂4 变为 2  // 位运算优化: b>>=1
    }

    return ans;
}

long long solution(char *s) {
    // 求s串每个字符c的数量
    int count[26] = {0};
    for (int i = 0; i < strlen(s); i++) {
        char c = s[i];
        count[c - 'a']++;
    }

    // "出现次数为奇数次的"字符的数量
    int odd = 0;
    for (int i = 0; i < 26; i++) {
        if (count[i] % 2 != 0) {
            odd++;
        }

        count[i] /= 2; // 只保留一半字符数量, 后续只需要用到回文串的左半部分,即一半的字符即可
    }

    // 如果"出现次数为奇数次的"字符的数量不止1个,则s串无法重组出回文串
    if (odd > 1) {
        return 0;
    }

    // 不重复的全排列数
    long long ans = fact[strlen(s) / 2];
    for (int i = 0; i < 26; i++) {
        // 假设 x == fact[count[i] / 2]
        // ans / x % mod
        // 等价于
        // ans * x的乘法逆元 % mod
        // 而x的乘法逆元为 fast_pow(x, mod-2, mod)
        ans = ans * fast_pow(fact[count[i]], MOD - 2) % MOD;
    }

    return ans;
}

int main() {
    // 初始化1~500的阶乘
    initFact();

    // 输入获取
    int t;
    scanf("%d", &t);

    while (t--) {
        char s[MAX_LEN];
        scanf("%s", s);
        // 核心代码调用
        printf("%lld\n", solution(s));
    }

    return 0;
}

C++算法源码

除法取模,乘法逆元,费马小定理,快速幂

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

#define MOD 1000000007
long long fact[501] = {0};

void initFact() {
    fact[0] = 1;

    for (int i = 1; i <= 500; i++) {
        fact[i] = i * fact[i - 1] % MOD;
    }
}

// 快速幂算法:用于求解 (a^b) % mod 的结果
long long fast_pow(long long a, long long b) {
    long long ans = 1; // 记录结果

    a %= MOD;

    // 快速幂算法是为了高效计算a^b, 举例
    // 3^5
    //  = 3 * 3^4
    //  = 3 * 9^2
    //  = 3 * 81^1
    //  = 3 * 81 * 81^0
    // 这个过程中如果发现b为奇数,则析出一个底a作为乘数, 实现 b-=1
    // 这个过程中如果发现b为偶数,则底a进行平方运算,实现 b/=2
    // 这个算法求解a^b的时间复杂度为O(log2(b)), 相较于O(b)算法十分高效
    while (b != 0) {
        if (b % 2 == 1) { // 位运算优化: if(b&1 == 1)
            // 3^5 析出来一个3后, 变为 3 * 3^4, 将b值从奇数变为偶数
            // 下面将析出的来3合入结果ans中, 则剩余3^4
            ans = ans * a % MOD;
            // b -= 1; // 可以不用此步, 因为后面b会整除2
        }

        // 3^4 变为 9^2
        a = a * a % MOD; // 底数3 变为 9
        b /= 2; // 幂4 变为 2  // 位运算优化: b>>=1
    }

    return ans;
}

long long solution(string &s) {
    // 求s串每个字符c的数量
    int count[26] = {0};
    for (int i = 0; i < s.length(); i++) {
        char c = s[i];
        count[c - 'a']++;
    }

    // "出现次数为奇数次的"字符的数量
    int odd = 0;
    for (int i = 0; i < 26; i++) {
        if (count[i] % 2 != 0) {
            odd++;
        }

        count[i] /= 2; // 只保留一半字符数量, 后续只需要用到回文串的左半部分,即一半的字符即可
    }

    // 如果"出现次数为奇数次的"字符的数量不止1个,则s串无法重组出回文串
    if (odd > 1) {
        return 0;
    }

    // 不重复的全排列数
    long long ans = fact[s.length() / 2];
    for (int i = 0; i < 26; i++) {
        // 假设 x == fact[count[i] / 2]
        // ans / x % mod
        // 等价于
        // ans * x的乘法逆元 % mod
        // 而x的乘法逆元为 fast_pow(x, mod-2, mod)
        ans = ans * fast_pow(fact[count[i]], MOD - 2) % MOD;
    }

    return ans;
}

int main() {
    // 初始化1~500的阶乘
    initFact();

    // 输入获取
    int t;
    cin >> t;

    while (t--) {
        string s;
        cin >> s;
        // 核心代码调用
        cout << solution(s) << endl;
    }

    return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/715624.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

25 avl树

目录 底层结构avl树的概念节点定义插入旋转验证删除全性能 1. 底层结构 前面对map/multimap/set/multiset进行了简单的介绍&#xff0c;在其文档介绍中发现&#xff0c;这几个容器有几个共同点是&#xff1a;其底层都是按照二叉搜索树来实现的&#xff0c;但是二叉搜索树有自…

【CSS in Depth2精译】1.1 层叠

CSS 本质上就是声明规则&#xff0c;并让这些特定的规则在各种情况下生效。一个类添加到某个元素上&#xff0c;则应用这个类包含的这一些样式&#xff1b;元素 X 是元素 Y 的一个子节点&#xff0c;则应用另一些样式。浏览器于是根据这些规则&#xff0c;判定所有样式生效的具…

使用 C# 进行面向对象编程:第 9 部分

使用 OOP 的用户活动日志 应用程序背后的关键概念 在这一部分中&#xff0c;我们将使用之前学到的一些 OOP 概念。我们将创建一个小型应用程序。在继续之前&#xff0c;请阅读我的文章user-activity-log-using-C-Sharp-with-sql-server/。在本课程中&#xff0c;我们将再次使…

springboot+vue+mybatis教师工作审核系统+PPT+论文+讲解+售后

随着社会不断进步与发展&#xff0c;生活节奏不断加快&#xff0c;信息已经成为我们生活中不可缺少的一部分&#xff0c;很多学校需要掌握大量的信息来了解特定学生的需求&#xff0c;传统的做法是组织大量的人力物力对学生散发调查表&#xff0c;然后对收集的信息进行统计并得…

PHP调用阿里云OSS的SDK封装成服务的完整指南与问题解决

在现代Web开发中&#xff0c;使用云存储来管理和存储大量的静态文件已经成为常态。阿里云OSS&#xff08;对象存储服务&#xff09;是其中一个非常受欢迎的选择。在这篇文章中&#xff0c;我们将详细讲解如何在PHP项目中集成并使用阿里云OSS SDK。 #### 一、前期准备 在开始之…

SSH概念、用途、详细使用方法

还是大剑师兰特&#xff1a;曾是美国某知名大学计算机专业研究生&#xff0c;现为航空航海领域高级前端工程师&#xff1b;CSDN知名博主&#xff0c;GIS领域优质创作者&#xff0c;深耕openlayers、leaflet、mapbox、cesium&#xff0c;canvas&#xff0c;webgl&#xff0c;ech…

【安装笔记-20240616-Windows-Gpg4win 证书管理器】

安装笔记-系列文章目录 安装笔记-20240616-Windows-Gpg4win 证书管理器 文章目录 安装笔记-系列文章目录安装笔记-20240616-Windows-Gpg4win 证书管理器 前言一、软件介绍名称&#xff1a;Gpg4win主页官方介绍 二、安装步骤测试版本&#xff1a;Gpg4win 4.3.1下载链接安装界面…

调用第三方系统的签名设计与校验实例讲解与实践

在现代软件开发中&#xff0c;调用第三方系统API已经成为常见需求。为了保证数据传输的安全性和完整性&#xff0c;许多API采用了签名机制。本文将详细讲解如何设计与校验调用第三方系统的签名&#xff0c;以确保双方通信的安全和可靠。 #### 一、签名机制的意义 签名机制主要…

ElasticSearch地理空间数据了解

ElasticSearch地理空间数据了解 使用场景 Elasticsearch 的地理空间数据处理功能在现代社会中有着广泛的应用&#xff0c;以下是一些常见的使用场景和方向&#xff1a; 1. 位置搜索和导航 本地服务发现&#xff1a;应用程序可以使用 Elasticsearch 查找用户附近的餐馆、商店…

awd工具安装

fscan(漏洞扫描) 下载 下载地址: Releases shadow1ng/fscan GitHub 把下载的文件放到指定文件目录里, 在文件的位置打开cmd 输入 fscan64.exe -h 192.168.1.1/24 ok了 接下来说说fscan的使用 使用 1.信息搜集: 存活探测(icmp) 端口扫描 2.爆破功能: 各类服务爆破(…

Django REST framework视图集与路由详解:深入理解ViewSet、ModelViewSet与路由映射器

系列文章目录 Django入门全攻略&#xff1a;从零搭建你的第一个Web项目Django ORM入门指南&#xff1a;从概念到实践&#xff0c;掌握模型创建、迁移与视图操作Django ORM实战&#xff1a;模型字段与元选项配置&#xff0c;以及链式过滤与QF查询详解Django ORM深度游&#xff…

Java | Leetcode Java题解之第160题相交链表

题目&#xff1a; 题解&#xff1a; public class Solution {public ListNode getIntersectionNode(ListNode headA, ListNode headB) {if (headA null || headB null) {return null;}ListNode pA headA, pB headB;while (pA ! pB) {pA pA null ? headB : pA.next;pB …

几何公差的设计和选用

保证轴承的旋转精度&#xff0c;提出圆柱度&#xff1b; 这里的轴肩部面 为了测量方便&#xff0c;使用圆跳动代替垂直度公差方便一些。

胡说八道(24.6.10)——数电与STM32

至此&#xff0c;信号与系统的简单笔记已经全部都写完了。其实&#xff0c;信号与系统的知识远远不只这些&#xff0c;总之&#xff0c;我的老师没讲完。其真实的原因是不在考试大纲里面。今天&#xff0c;看到一个短视频——学习的意义。其中有句话说&#xff0c;“因为考试不…

Spring MVC详解(上)

一、Spring MVC初步认识 1.1介绍 Spring MVC是Spring Framework提供的Web组件&#xff0c;全称是Spring Web MVC,是目前主流的实现MVC设计模式的框架&#xff0c;提供前端路由映射、视图解析等功能 Java Web开发者必须要掌握的技术框架 1.2MVC是什么 MVC是一种软件架构思想…

证明 指数分布 的期望和方差

指数分布 指数分布&#xff08;Exponential Distribution&#xff09;是一种常见的连续型概率分布&#xff0c;通常用于描述事件之间的时间间隔。假设随机变量 ( X ) 服从参数为 ( \lambda ) 的指数分布&#xff0c;记作 指数分布的概率密度函数&#xff08;PDF&#xff09;…

【教程】设置GPU与CPU的核绑(亲和力Affinity)

转载请注明出处&#xff1a;小锋学长生活大爆炸[xfxuezhagn.cn] 如果本文帮助到了你&#xff0c;欢迎[点赞、收藏、关注]哦~ 简单来说&#xff0c;核绑&#xff0c;或者叫亲和力&#xff0c;就是将某个GPU与指定CPU核心进行绑定&#xff0c;从而尽可能提高效率。 推荐与进程优先…

Linux源码阅读笔记02-进程原理及系统调用

进程和进程的生命周期 进程&#xff1a;指计算机中已运行的程序。进程本身不是基本的运行单位&#xff0c;而是线程的容器。程序本身不是基本的运行单位&#xff0c;而是线程的容器。程序是指令、数据和组织形式的描述&#xff0c;进程才是程序的真正运行实例。Linux内核把进程…

《人生海海》读后感

麦家是写谍战的高手&#xff0c;《暗算》《风声》等等作品被搬上荧屏后&#xff0c;掀起了一阵一阵的收视狂潮。麦家声名远扬我自然是知道的&#xff0c;然而我对谍战似乎总是提不起兴趣&#xff0c;因此从来没有拜读过他的作品。这几天无聊时在网上找找看看&#xff0c;发现了…

使用 Oracle SQL Developer 导入数据

使用 Oracle SQL Developer 导入数据 1. 导入过程 1. 导入过程 选择要导入数据的表&#xff0c; 然后单击右键&#xff0c;选择"导入数据"&#xff0c; 浏览本地文件&#xff0c;选择正确的工作表&#xff0c; 按默认&#xff0c; 按默认&#xff0c; 根据情况修改&…