Portal

大致题意: 给定一个偶数长度(\(n \leq 10 ^ 5\))的字符串, 只包含大小写字母. 有q(\(q \leq 10 ^ 5\))次询问, 每次指定两个位置, 要求通过交换字符, 使这两个类型的字符在串同一边并且对于其他类型的字符, 不能跨过串的中线(也就是说必须在一边, 但是可以不跟指定的字符一边), 求方案数模\(1e9 + 7\)

Solution

这个题目很像atcoder啊

考虑去掉多余的状态, 事实上只有\(52 ^ 2 = 2704\)种状态, 其他的询问都是多余的.

考虑钦定两种字母,O(n)计算方案数. 发现答案是\(\frac{(\frac{n}{2})! ^ 2}{\prod {cnt_i !}}\) 那么就只需要考虑如何把剩下的50种字母塞进\(\frac{n}{2} - cnt_i - cnt_j\)里面去;

现在就转化成为如何计算背包方案数, 在不每次重新计算的情况下.

考虑背包具有子问题的自我概括性. 那么我们就只要从源头开始, 沿着转移方向一步一步消除影响即可, 这个套路也可以运用到一部分非可减性dp中, 当然, 如果能写成矩阵的话就不用这么麻烦了.

Code

#include<bits/stdc++.h>
using namespace std;
#define rep(i, a, b) for(int i = (a), i##_end_ = (b); i <= i##_end_; ++i)
#define drep(i, a, b) for(int i = (a), i##_end_ = (b); i >= i##_end_; --i)
#define clar(a, b) memset((a), (b), sizeof(a))
#define debug(...) fprintf(stderr, __VA_ARGS__)
#define Debug(s) debug("The massage in line %d, Function %s: %s\n", __LINE__, __FUNCTION__, s)
typedef long long LL;
typedef long double LD;
int read() {
char ch = getchar();
int x = 0, flag = 1;
for(;!isdigit(ch); ch = getchar()) if(ch == '-') flag *= -1;
for(;isdigit(ch); ch = getchar()) x = x * 10 + ch - 48;
return x * flag;
}
void write(LL x) {
if(x < 0) putchar('-'), x = -x;
if(x >= 10) write(x / 10);
putchar(x % 10 + 48);
} const int Maxn = 100009, Maxk = 60, Mod = (int)1e9 + 7;
char s[Maxn];
int n, q, dp[Maxn], cnt[Maxk];
int predict[Maxk][Maxk], tmpDp[Maxn];
int fac[Maxn], invFac[Maxn]; int fpm(int base, int tims) {
int r = 1;
while (tims) {
if (tims & 1) r = 1ll * base * r % Mod;
base = 1ll * base * base % Mod;
tims >>= 1;
}
return r;
} void init() {
scanf("%s", s + 1); n = strlen(s + 1);
rep (i, 1, n)
if (isupper(s[i])) ++cnt[s[i] - 'A' + 1];
else ++cnt[s[i] - 'a' + 27]; /* Note */
dp[0] = 1;
rep (i, 1, 52) {
if (!cnt[i]) continue;
drep (j, n, cnt[i]) (dp[j] += dp[j - cnt[i]]) %= Mod;
}
/* Note */ fac[0] = 1;
rep (i, 1, n) fac[i] = fac[i - 1] * 1ll * i % Mod;
invFac[n] = fpm(fac[n], Mod - 2);
drep (i, n - 1, 0) invFac[i] = invFac[i + 1] * (i + 1ll) % Mod;
} void solve() {
rep (i, 1, 52)
rep (j, 1, i) {
if (!cnt[i] || !cnt[j]) continue;
rep (l, 0, n) tmpDp[l] = dp[l];
rep (l, cnt[i], n) {
(tmpDp[l] -= tmpDp[l - cnt[i]]) %= Mod;
(tmpDp[l] += Mod) %= Mod;
} if (i == j) {
predict[i][i] = tmpDp[n / 2];
continue;
} rep (l, cnt[j], n) {
(tmpDp[l] -= tmpDp[l - cnt[j]]) %= Mod;
(tmpDp[l] += Mod) %= Mod;
} predict[i][j] = predict[j][i] = tmpDp[n / 2];
} int W = fac[n / 2] * 1ll * fac[n / 2] % Mod;
rep (i, 1, 52)
if (cnt[i] > 0) W = 1ll * W * invFac[cnt[i]] % Mod; q = read();
rep (i, 1, q) {
int x = read(), y = read();
if (isupper(s[x])) x = s[x] - 'A' + 1; else x = s[x] - 'a' + 27;
if (isupper(s[y])) y = s[y] - 'A' + 1; else y = s[y] - 'a' + 27;
printf("%d\n", 2ll * W % Mod * predict[x][y] % Mod);
}
} int main() {
freopen("Cf1111D.in", "r", stdin);
freopen("Cf1111D.out", "w", stdout); init();
solve(); #ifdef Qrsikno
debug("\nRunning time: %.3lf(s)\n", clock() * 1.0 / CLOCKS_PER_SEC);
#endif
return 0;
}

[CF1111D] Destory the Colony的更多相关文章

  1. [CF1111D]Destroy the Colony

    题目大意:有一个长度为$n(n\leqslant10^5,n=0\pmod2)$的字符串,字符集大小为$52$,有$q(q\leqslant10^5)$次询问,每次询问第$x,y$个字符在这个字符串的 ...

  2. C++中 destory() 和deallocate()以及delete函数的相关性和区别性

    这里非常的绕口  需要仔细的来看看: destory(): 显示调用一个对象的析构函数 相当于释放一个对象需要释放的一些动态内存 为下次真正释放对象做准备 deallocate():真正的释放一个内存 ...

  3. [BZOJ3872][Poi2014]Ant colony

    [BZOJ3872][Poi2014]Ant colony 试题描述 There is an entrance to the ant hill in every chamber with only o ...

  4. Delphi 对象的创建(create)与释放(free/destory)

    Delphi 对象的创建(create)与释放(free/destory) 1.Create参数为:nil/self/application的区别,最好能看到实际效果的区别 例如: My := TMy ...

  5. Codeforces 474 F. Ant colony

    线段树求某一段的GCD..... F. Ant colony time limit per test 1 second memory limit per test 256 megabytes inpu ...

  6. Unity Destory

    Object.Destroy     public static function Destroy(obj: Object, t: float = 0.0F): void; public static ...

  7. android点击返回键,如何做到不destory当前activity,只是stop。重新返回该activity的 时候可以直接使用,不需要创建新的activity实例

    问题描述,如题目: android点击返回键,顺序执行 pause,stop,destory. 以至于想重新进入这个activity的时候还要重新执行onCreate()方法,那么如何解决不再重新执行 ...

  8. Codeforces Round #271 (Div. 2) F. Ant colony 线段树

    F. Ant colony time limit per test 1 second memory limit per test 256 megabytes input standard input ...

  9. 【BZOJ3872】Ant colony(二分,动态规划)

    [BZOJ3872]Ant colony(二分,动态规划) 题面 又是权限题... Description There is an entrance to the ant hill in every ...

随机推荐

  1. Python序列——元组

    元组是什么 1 创建元组 2 访问元组中的值 3 更新元组中的元素 4 删除元组中的元素或者元组本身 元组相关操作 内建函数对元组的支持 1 序列类型函数 2 元组内建函数 元组的特殊性 1. 元组是 ...

  2. Codeforces Round #402 (Div. 2) D String Game —— 二分法

    D. String Game time limit per test 2 seconds memory limit per test 512 megabytes input standard inpu ...

  3. UVA1635 Irrelevant Elements —— 唯一分解定理 + 二项式定理

    题目链接:https://vjudge.net/problem/UVA-1635 (紫书320) 题解: 1.根据二项式定理, 可得递推公式: C(n,k) = (n-k+1)/k * C(n, k- ...

  4. c/c++通用内存泄漏检测框架GMFD(General Memory Fault Detection Framework)

    http://qa.baidu.com/blog/?p=171 1 背景: x86平台有完善的用户态检测内存工具比如valgrind等,可以监控程序运行中详细的内存信息,从而精确定位内存问题.然而随着 ...

  5. android读取apk中已经存在的数据库信息

    在android数据库编程方面,大家有没有遇到过,我要从指定位置的已经存在的数据库来进行操作的问题.之前我尝试了很多方法都没有成功,后来找到了解决的方法.   下面说明下这段代码的意思,第一步先判断在 ...

  6. 编译thrift外篇-关于默认链接包-(使用mapkeeper运行leveldb成功)

    根据 https://stackoverflow.com/questions/9922949/how-to-print-the-ldlinker-search-path 使用 ldconfig -v ...

  7. hadoop应用场景

    大数据量存储:分布式存储 日志处理: Hadoop擅长这个 海量计算: 并行计算 ETL:数据抽取到oracle.mysql.DB2.mongdb及主流数据库 使用HBase做数据分析: 用扩展性应对 ...

  8. No java virtual machine ....

    运行Eclipse提示No java virtual machine   版权声明:本文原创作者:一叶飘舟 作者博客地址:http://blog.csdn.net/jdsjlzx http://blo ...

  9. 苹果app(iOS app)的URL schemes

    最近折腾iOS快捷启动应用或应用内的某个动作的神器launch center pro (LCP),发现很多国产app并没有被LCP官方收录,所以不得不想办法找到app的url schemes. 下面是 ...

  10. linear_classifier.py

    import numpy as np from cs231n.classifiers.linear_svm import * from cs231n.classifiers.softmax impor ...