D. String Mark
time limit per test

4 seconds

memory limit per test

256 megabytes

input

standard input

output

standard output

At the Byteland State University marks are strings of the same length. Mark x is considered better than y if string y is lexicographically smaller than x.

Recently at the BSU was an important test work on which Vasya recived the mark a. It is very hard for the teacher to remember the exact mark of every student, but he knows the mark b, such that every student recieved mark strictly smaller than b.

Vasya isn't satisfied with his mark so he decided to improve it. He can swap characters in the string corresponding to his mark as many times as he like. Now he want to know only the number of different ways to improve his mark so that his teacher didn't notice something suspicious.

More formally: you are given two strings ab of the same length and you need to figure out the number of different strings c such that:

1) c can be obtained from a by swapping some characters, in other words c is a permutation of a.

2) String a is lexicographically smaller than c.

3) String c is lexicographically smaller than b.

For two strings x and y of the same length it is true that x is lexicographically smaller than y if there exists such i, that x1 = y1, x2 = y2, ..., xi - 1 = yi - 1, xi < yi.

Since the answer can be very large, you need to find answer modulo 109 + 7.

Input

First line contains string a, second line contains string b. Strings a, b consist of lowercase English letters. Their lengths are equal and don't exceed 106.

It is guaranteed that a is lexicographically smaller than b.

Output

Print one integer  — the number of different strings satisfying the condition of the problem modulo 109 + 7.

Examples
input
abc
ddd
output
5
input
abcdef
abcdeg
output
0
input
abacaba
ubuduba
output
64
Note

In first sample from string abc can be obtained strings acb, bac, bca, cab, cba, all of them are larger than abc, but smaller than ddd. So the answer is 5.

In second sample any string obtained from abcdef is larger than abcdeg. So the answer is 0.

题目大意:给两个字符串a,b,重组a字符串得到c,使得c的字典序大于a小于b,问方案数.

分析:比较有难度,一开始没能想出来.

其实这道题有点像数位dp,有上下界嘛,求个数.但是不同的是要求的字符串需要是a重组得到的,每个字符的个数是一定的,也就是说在当前位放了一个数,可能会对后面的决策造成影响.于是就可以用记忆化搜索来解决.

设f[i][0/1][0/1]表示前i位中是否达到上界和是否达到下界的方案数.类似于数位dp,先处理既达到上界又达到下界的,如果当前处理到第i位并不是只能选一个数字的话,那么可以把这个过程拆成处理到达上界的部分和处理到达下界的部分.如果只能选一个数字,那么这个数字的个数-1,搜下去.再处理上下界的情况.将上下界的数字的个数分别-1,搜下去,这里要分别处理.

剩下的就是处理位于下界+1和上界-1之间的数了.枚举放哪一个,方案数就是排列数,只不过元素允许重复,需要用不全相异元素的排列公式来计算,即如果总共有n个数,第i个数有ni个,那么方案数为n! / (n1! * n2! * ...... * nn!).最后将所有转移的答案累加就是问题的答案了.

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <string>
#include <cmath> using namespace std; typedef long long ll; const int maxn = , mod = 1e9 + ;
ll f[maxn][][], len, a[maxn], b[maxn], num[maxn], jie[maxn];
char s1[maxn], s2[maxn]; ll qpow(ll a, ll b)
{
ll res = ;
while (b)
{
if (b & )
res = (res * a) % mod;
a = (a * a) % mod;
b >>= ;
}
return res;
} ll solve(ll cur, bool up, bool down)
{
ll ans = ;
if (f[cur][up][down] != -)
return f[cur][up][down];
if (up && down && a[cur] == b[cur] && num[a[cur]] > )
{
num[a[cur]]--;
ll temp = solve(cur + , up, down);
num[a[cur]]++;
return f[cur][up][down] = temp;
}
if (up && num[b[cur]])
{
num[b[cur]]--;
ans += solve(cur + , , );
ans %= mod;
num[b[cur]]++;
}
if (down && num[a[cur]])
{
num[a[cur]]--;
ans += solve(cur + , , );
ans %= mod;
num[a[cur]]++;
}
ll temp = ;
for (ll i = ; i <= ; i++)
temp = (temp * jie[num[i]]) % mod;
temp = qpow(temp, mod - );
int upx = (up ? b[cur] - : ), downx = (down ? a[cur] + : );
ll left = len - cur;
for (ll i = downx; i <= upx; i++)
{
if (num[i] > )
ans += jie[left] * temp % mod * num[i] % mod; //因为num[i]的数量要-1,所以分母的阶乘要减少num[i]
ans %= mod;
}
return f[cur][up][down] = ans;
} int main()
{
jie[] = ;
for (ll i = ; i <= ; i++)
jie[i] = (jie[i - ] * i) % mod;
scanf("%s", s1 + );
scanf("%s", s2 + );
len = strlen(s1 + );
for (ll i = ; i <= len; i++)
{
a[i] = s1[i] - 'a' + ;
num[a[i]]++;
b[i] = s2[i] - 'a' + ;
}
memset(f, -, sizeof(f));
cout << solve(,,) << endl; return ;
}

Codeforces 895.D String Mark的更多相关文章

  1. String Mark Codeforces - 895D

    一看好像会做的样子,就去做了一下,结果 猝不及防地T掉了 赶紧查了一下,没有死循环,复杂度也是对的,无果,于是翻了题解 题解没看懂,但是找到了标程,然后发现我被卡常了... 而且好像当时还过了前10个 ...

  2. CodeForces 797C Minimal string:贪心+模拟

    题目链接:http://codeforces.com/problemset/problem/797/C 题意: 给你一个非空字符串s,空字符串t和u.有两种操作:(1)把s的首字符取出并添加到t的末尾 ...

  3. Codeforces 827E Rusty String - 快速傅里叶变换 - 暴力

    Grigory loves strings. Recently he found a metal strip on a loft. The strip had length n and consist ...

  4. Codeforces 797C - Minimal string

    C. Minimal string 题目链接:http://codeforces.com/problemset/problem/797/C time limit per test 1 second m ...

  5. codeforces 825F F. String Compression dp+kmp找字符串的最小循环节

    /** 题目:F. String Compression 链接:http://codeforces.com/problemset/problem/825/F 题意:压缩字符串后求最小长度. 思路: d ...

  6. Codeforces - 1117E - Crisp String - 进制 - 交互

    https://codeforces.com/problemset/problem/1117/E 就用abc表示数字来给每个数编码,编完直接问出移动的结果,反构造就行了,比C和D还简单. #inclu ...

  7. codeforces 828 C. String Reconstruction(思维+优先队列)

    题目链接:http://codeforces.com/contest/828/problem/C 题解:有点意思的题目,可用优先队列解决一下具体看代码理解.或者用并查集或者用线段树都行. #inclu ...

  8. codeforces 779 D. String Game(二分)

    题目链接:http://codeforces.com/contest/779/problem/D 题意:给你一段操作序列,按顺序依次删掉字符串1中相应位置的字符,问你最多能按顺序删掉多少个字符,使得s ...

  9. Codeforces 494B Obsessive String

    http://www.codeforces.com/problemset/problem/494/B 题意:给出两个串S,T,求有几种将S分成若干个子串,满足T都是这若干个子串的子串. 思路:f[n] ...

随机推荐

  1. HDU-1053:Advanced Fruits(LCS+路径保存)

    链接:HDU-1053:Advanced Fruits 题意:将两个字符串合成一个串,不改变原串的相对顺序,可将相同字母合成一个,求合成后最短的字符串. 题解:LCS有三种状态转移方式,将每个点的状态 ...

  2. C/C++语言基础

    1. 一个子类中含有其他类对象,则构造函数的顺序是? 先执行基类的(如果基类当中有虚基类,要先执行虚基类的,其他基类则按照声明派生类是的顺序依次执行),在执行成员对象的,最后执行自己的. 2.spri ...

  3. linux ——使用find如何快速替换所有相同参数

    在生成环境上有时候需要大规模修改某一配置里的参数,但是该参数存在多个地方,比如IP地址 端口 项目名等,特别是项目名称混乱想统一 find  /项目地址 -type f |xargs grep &qu ...

  4. 深入react技术栈解读

    1. react实现virtual DOM ,如果要改变页面的内容,还是需要执行DOM操作,比原生操作DOM多了virtualDOM的操作(计算,对比等), 应该是更耗性能??? 2. react特点 ...

  5. 原生开发小程序 和 wepy 、 mpvue 对比

    1.三者的开发文档以及介绍: 原生开发小程序文档:点此进入 wepy 开发文档:点此进入 mpvue 开发文档:点此进入 2.三者的简单对比: 以下用一张图来简单概括三者的区别: 小程序支持的是 WX ...

  6. ES6的新特性(9)——对象的扩展

    对象的扩展 属性的简洁表示法 ES6 允许直接写入变量和函数,作为对象的属性和方法.这样的书写更加简洁. const foo = 'bar'; const baz = {foo}; baz // {f ...

  7. 栈和队列在python中的实现

    栈和队列是两种基本的数据结构,同为容器类型.两者根本的区别在于: stack:后进先出 queue:先进先出 PS:stack和queue是不能通过查询具体某一个位置的元素而进行操作的.但是他们的排列 ...

  8. 【Leetcode】 328. Odd Even Linked List

    Given a singly linked list, group all odd nodes together followed by the even nodes. Please note her ...

  9. 敏捷开发之Scrum站立会议

    Scrum是迭代式增量软件开发过程,通常用于敏捷开发.站立会议通常指Scrun方法中的每日站立会议.顾名思义,是每天以站姿的方式召开的会议.以下从功能及要点方面对其进行解释说明: 功能:     1. ...

  10. 【Nginx】转:Nginx try_files

    原来的配置是这样的: location / { try_files $uri $uri/ /index.php; index index.html index.htm index.php; } loc ...