链接:https://ac.nowcoder.com/acm/contest/9680/J
来源:牛客网
白浅经过一段时间对字符串的学习之后,学会了如何使用递归输出一个字符串的所有全排列(虽然 C++ 中有自带的函数),甚至学会了如何输出所有去重后的全排列(即“本质不同的全排列”)!她拿到了一个字符串 S,现在她将 S 的所有本质不同的全排列按字典序大小进行排序。假如总共有 k 个本质不同的字符串,则这些字符串按照字典序大小分别编号为 1.2.3…k,。白浅在这些字符串中任取了两个字符串 A B,现在她想知道 A 的编号减去 B 的编号等于多少。
输入描述:
输入的第一行包含一个整数 n,代表字符串的长度。(1≤n≤2∗10^5)
接下来两行分别给出一个长度为 n 的字符串,分别代表 A, B。注意:字符串仅包含大写字母。
保证 A B 都是同一个字符串的全排列。答案对 10^9+7 取模。
输出描述:
输出一个整数代表结果
输入
4
ABBB
BBBA
输出
1000000004
有重复元素的全排列,n为全部元素的数目,n1…nk,为第一种元素到最后一种元素的数目,x为全排列本质不同的排列数目,n1!n2!n3!n4!..nk!x=n!
x=n!/(n1!n2!..nk!) (学习可见蓝书第二章2.1数学基础问题四(104页))。
对于A字符串找到前面有多少个比它小的数字cou1,B串找的前面比它小的数目cou2,二者相减取模。
#include <stdio.h>
#include <string.h>
char s1[1000001], s2[1000001], st[11];
long long int num[27], num1[27], num2[27], order1[27], cnt = 0, order[27], cou1 = 0, cou2 = 0, cou = 0;
long long int ans = 1, ans1, ans2, mod = 1000000007;
long long int qun(long long int a, long long int b)
{
long long int ans = 1;
while (b)
{
if (b & 1)
{
ans = ans * a;
ans = ans % mod;
}
a = a * a;
a %= mod;
b >>= 1;
}
return ans;
}
int main()
{
#ifdef ONLINE_JUDGE
#else
freopen("in.txt", "r", stdin);
#endif
long long int i, j, n;
scanf("%lld", &n);
fgets(st, 11, stdin);
scanf("%s", s1);
fgets(st, 11, stdin);
scanf("%s", s2);
for (i = 0; i < n; i++)
{
num[s1[i] - 'A']++;
num1[s1[i] - 'A']++;
num2[s1[i] - 'A']++;
}
for (i = 0; i < 26; i++)
{
if (num[i] > 0)
{
order[i] = cnt;
order1[cnt] = i;
cnt++;
}
}
for (i = 2; i <= n; i++)
{
ans = (ans * i) % mod;
}
for (i = 0; i < 26; i++)
{
if (num[i] > 0)
{
for (j = 2; j <= num[i]; j++)
{
ans = ans * qun(j, mod - 2);
ans = ans % mod;
}
}
}
ans1 = ans, ans2 = ans;
for (i = 0; i < n; i++)
{
ans1 = ans1 * qun(n - i, mod - 2);
ans1 %= mod;
if (order[s1[i] - 'A'] != 0)
{
for (j = 0; j < order[s1[i] - 'A']; j++)
{
cou1 += ((ans1 * num1[order1[j]]) % mod);
cou1 %= mod;
}
}
ans1 *= num1[s1[i] - 'A'];
ans1%=mod;
num1[s1[i] - 'A']--;
}
for (i = 0; i < n; i++)
{
ans2 = ans2 * qun(n - i, mod - 2);
ans2 %= mod;
if (order[s2[i] - 'A'] != 0)
{
for (j = 0; j < order[s2[i] - 'A']; j++)
{
cou2 += ((ans2 * num2[order1[j]]) % mod);
cou2 %= mod;
}
}
ans2 *= num2[s2[i] - 'A'];
ans2 %= mod;
num2[s2[i] - 'A']--;
}
printf("%lld\n", ((cou1 - cou2) % mod + mod) % mod);
return 0;
}