codeforces 895D String Mark
来源:互联网 发布:决战武林所有进阶数据 编辑:程序博客网 时间:2024/06/14 19:36
简略题意:给出等长的AB串,问有多少A串的重排列得到的串字典序大于A串,小于B串。
dp[i][0/1][0/1]代表当前处理到第i个位置,之前的选择有没有贴在上边界,有没有贴在下边界,考虑贴近上边界,下边界,或者不贴近边界,得到若干转移。
唯一需要注意的地方就是对于直接转移到dp[i][0][0]的状态,直接计算有重复元素的重排列即可,可以通过直接处理除数扣掉26的常数。
#define others#ifdef poj#include <iostream>#include <cstring>#include <cmath>#include <cstdio>#include <algorithm>#include <vector>#include <string>#endif // poj#ifdef others#include <bits/stdc++.h>#endif // others//#define file#define all(x) x.begin(), x.end()using namespace std;const double eps = 1e-8;int dcmp(double x) { if(fabs(x)<=eps) return 0; return (x>0)?1:-1;};typedef long long LL;/*题意:问a字符串有多少种排列使得得到的字符串c的字典序大于a,小于b。问方案数。*/namespace solver { const LL mod = 1e9+7; LL n; char a[1100000], b[1100000]; LL v[27], s[27]; LL fac[1100000], dp[1100000][2][2], Inv[1100000]; void init() { fac[0] = 1; for(LL i = 1; i < 1100000; i++) fac[i] = fac[i-1] * i % mod; memset(dp, -1, sizeof dp); } LL Pow(LL a, LL b) { LL res = 1; while(b) { if(b & 1) { res *= a; res %= mod; } b >>= 1; a *= a;a %= mod; } return res; } LL dfs(LL i, LL up, LL down) { if(~dp[i][up][down]) return dp[i][up][down]; if(i > n) return 0; LL ans = 0; LL sum = n - i + 1; if(up && down && v[b[i]] && a[i] == b[i]) { v[a[i]] --; ans += dfs(i+1, 1, 1); if(ans >= mod) ans %= mod; v[a[i]] ++; return dp[i][up][down] = ans; } if(up && v[a[i]]) { v[a[i]] --; ans += dfs(i+1, 1, 0); if(ans >= mod) ans %= mod; v[a[i]] ++; } if(down && v[b[i]]) { v[b[i]] --; ans += dfs(i+1, 0, 1); if(ans >= mod) ans %= mod; v[b[i]] ++; } LL tmp = 1; for(int k = 1; k <= 26; k++) { tmp *= fac[v[k]]; tmp %= mod; } LL tmp_inv = Pow(tmp, mod-2); int head = (down)?b[i]+1:1, tail = (up)?a[i]-1:26; for(int j = head; j <= tail; j++) { if(v[j] == 0) continue; v[j]--; ans += fac[sum - 1] * tmp_inv % mod * (v[j]+1)%mod; if(ans >= mod) ans %= mod; v[j]++; } return dp[i][up][down] = ans; } void solve() { init(); scanf("%s%s", b + 1, a + 1); n = strlen(a + 1); int k = 0; for(LL i = 1; i <= n; i++) { b[i] = b[i] - 'a' + 1; if(v[b[i]] == 0) k++; v[b[i]]++; } for(int i = 1; i <= n; i++) a[i] = a[i] - 'a' + 1; printf("%lld\n", dfs(1, 1, 1)); }}int main() { #ifdef file freopen("gangsters.in", "r", stdin); freopen("gangsters.out", "w", stdout); #endif // file solver::solve(); return 0;}
阅读全文
0 0
- codeforces 895D String Mark
- Codeforces Round #448 (Div. 2) D. String Mark
- Codeforces Round #448 (Div. 2)D. String Mark(组合数学)
- 【Codeforces 682D】【String】
- 【codeforces 779D】String Game
- codeforces 779 D. String Game
- Codeforces 868 D Huge String
- codeforces 123 D String(后缀自动机 SAM)
- Codeforces 196 D. The Next Good String
- codeforces 709 D Recover the String (构造)
- Codeforces 779D String Game 二分
- codeforces 778D. String Game (二分搜索)
- 【Codeforces-402D】-String Game (二分)
- Codeforces 779D String Game 【二分】
- CodeForces 779D String Game【二分答案】
- codeforces 895D
- codeforces school mark
- Codeforces Beta Round #52 (Div. 2) D - Changing a String
- 10分钟让你明白MySQL是如何利用索引的
- 数据结构实验之图论五:从起始点到目标点的最短步数(BFS)
- JQ传统轮播图
- 服务器安装系统
- linux基础命令
- codeforces 895D String Mark
- 切割nohup.out的脚本
- Linux系统下,Oracle数据库的备份与还原
- Vue权限管理解决方案
- java jdk安装
- 借助sip呼叫浅析sip server
- ubuntu切换到win10之后耳机没声音
- HDOJ2131 Probability
- 判断网络状态是否可用