codeforces 895D
来源:互联网 发布:windows日志服务器搭建 编辑:程序博客网 时间:2024/05/21 10:49
(组合数学)
题意:给定两个由全英文字母构成的字符串
思路:
首先统计
第一种数目比较好求,直接求出
在求本身排列是第几位的过程中,用
(公式懒得写了..这个编辑器有点不太会用。话说,还是要多敲题,这题思路虽然出来了,敲得贼慢…)
代码:
#include <cstdio>#include <cstring>#include <algorithm>#define LL long longusing namespace std;const int maxn = 1000010;const LL mod = 1e9 + 7;bool s2_smaller, s2_bigger;int num[30], sum[30];char s1[maxn], s2[maxn];LL fac[maxn], inv_fac[maxn];LL pow(LL a, LL b) { LL ret = 1; while(b) { if(b&1) ret = ret * a % mod; a = a * a % mod; b >>= 1; } return ret;}void pre_treat(int len) { fac[0] = inv_fac[0] = 1; for(int i=1; i<=len; i++) { fac[i] = (LL)i * fac[i-1] % mod; inv_fac[i] = pow((LL)fac[i], mod-2); }}void init(int len) { for(int i=0; i<len; i++) num[s1[i]-'a'] ++; sum[0] = num[0]; for(int i=1; i<26; i++) sum[i] = sum[i-1] + num[i];}void transform_s2(int len) { init(len); for(int i=0; i<len; i++) { int alpha = s2[i] - 'a'; if(!s2_smaller && !s2_bigger) { if(num[alpha]) num[alpha] --; else { for(int j=alpha-1; j>=0; j--) if(num[j]) { s2_smaller = true; //puts("small"); s2[i] = j + 'a'; num[j] --; break ; } if(s2_smaller) continue ; for(int j=alpha+1; j<26; j++) if(num[j]) { s2_bigger = true; //puts("big"); s2[i] = j + 'a'; num[j] --; break ; } if(s2_bigger) continue ; } } else if(s2_smaller) { for(int j=25; j>=0; j--) if(num[j]) { s2[i] = j + 'a'; num[j] --; break ; } } else {//s2_bigger for(int j=0; j<26; j++) if(num[j]) { s2[i] = j + 'a'; num[j] --; break ; } } }}LL solve(char *s, int len) { init(len); LL ret = 0; for(int i=0; i<len; i++) { int alpha = s[i] - 'a'; if(alpha > 0 && sum[alpha-1] > 0) { LL t1 = fac[len-i-1], t2 = 0; for(int j=0; j<26; j++) if(num[j]) { t1 = t1 * inv_fac[num[j]] % mod; if(j < alpha) t2 = (t2 + num[j]) % mod; } ret = (ret + t1 * t2 % mod) % mod; } //printf("------i:%d ret:%I64d\n",i,ret); num[alpha] --; for(int j=alpha; j<26; j++) sum[j] --; } return ret;}int main() { //freopen("test.txt","r",stdin); s2_smaller = s2_bigger = false; scanf("%s%s",s1,s2); int len = strlen(s1); pre_treat(len); transform_s2(len); LL l = solve(s1, len), r = solve(s2, len); //printf("l:%I64d r:%I64d\n",l,r); LL ans = (r - l + mod) % mod; if(!s2_smaller && !s2_bigger) ans = (ans - 1 + mod) % mod; else if(s2_smaller) ans = ans; else ans = (ans - 1 + mod) % mod; printf("%I64d\n",ans); return 0;}
阅读全文
1 0
- codeforces 895D
- codeforces 895D String Mark
- CodeForces 617D CodeForces 617D
- CodeForces 101D
- CodeForces 103D
- CodeForces 222D Olympiad
- codeforces 242d
- CodeForces 111D
- 【codeforces】3D
- CodeForces 127D Password
- codeforces 257D. Sum
- Codeforces 292D
- Codeforces 275D
- Codeforces 126D
- Codeforces 337d
- Codeforces D. Points
- codeforces 96D Volleyball
- Codeforces 165D
- SQL入门 3 管理数据库对象
- U盘怎样传输大于4G的文件?
- 应用示例:图像文字识别
- [微信小程序]提交表单返回成功后自动清空表单的值
- Git安装配置与GitHub注册及简单使用
- codeforces 895D
- Log4Net使用详解(续)
- 【1701H1】【穆晨】【171202】连续第五十三天总结
- SQL注入(手工注入)
- 如何提高opengl的显示效率及Android系统的子模块Graphic的总体架构
- 圆桌硬币问题
- 1111
- php 微信开发之新增上传/获取下载临时素材
- Python存储csv文件