【Codeforces1111D_CF1111D】Destroy the Colony(退背包_组合数学)
题目:
翻译:
【已提交至洛谷CF1111D】
有一个恶棍的聚居地由几个排成一排的洞穴组成,每一个洞穴恰好住着一个恶棍。
每种聚居地的分配方案可以记作一个长为偶数的字符串,第\(i\)个字符代表第\(i\)个洞里的恶棍的类型。
如果一个聚居地的分配方案满足对于所有类型,该类型的所有恶棍都住在它的前一半或后一半,那么钢铁侠可以摧毁这个聚居地。
钢铁侠的助手贾维斯有不同寻常的能力。他可以交换任意两个洞里的野蛮人(即交换字符串中的任意两个字符)。并且,他可以交换任意次。
现在钢铁侠会问贾维斯\(q\)个问题。每个问题,他会给贾维斯两个数\(x\)和\(y\)。贾维斯要告诉钢铁侠,从当前的聚居地分配方案开始,他可以用他的能力创造多少种不同的方案,使得与原来住在第\(x\)个洞或第\(y\)个洞中的恶棍类型相同的所有恶棍都被分配到聚居地的同一半,同时满足钢铁侠可以摧毁这个聚居地。
如果某一个洞里的恶棍在两种方案中类型不同,则这两种方案是不同的。
输入
第一行包含一个字符串\(s\) (\(2\leq |s| \leq 10^5\)),表示初始的聚居地分配方案。字符串\(s\)包含小写和大写英文字母,且长度为偶数。
第二行包含一个整数\(q\)——询问的数量。
接下来的\(q\)行中的第\(i\)行包含两个整数\(x_i\)和\(y_i\) (\(1\leq x_i, y_i \leq |s|\))——第\(i\)个问题中给贾维斯的两个整数。
输出
对于每个问题输出可能的分配方案数模\(10^9+7\)。
分析:
前置技能
首先需要知道一个叫做“退背包”的东西,即给定\(n\)个物品,每个物品有体积\(w[i]\),求对于每一个\(i(1\leq i \leq n)\),当不存在第\(i\)个物品时,装满容量为\(m\)的背包的方案数。
暴力做法是对于每种\(n-1\)个物品的情况都\(O(nm)\)做一次0-1背包,总复杂度\(O(n^2m)\),非常不优秀。“退背包”的做法是首先对全部\(n\)个物品做一遍背包,设\(f[i]\)为装满容量为\(i\)的背包的方案数。如果当前第\(i\)个物品不存在,则从\(f[k](v[i]\leq ki \leq m)\)中减去包含\(i\)的方案数。设此时答案为\(g[k]\),则:
f[k](0\leq k < v[i])\\
f[k]-g[k-v[i]](v[i]\leq k \leq m)
\end{cases}
\]
于是对于每一种物品不存在的情况都可以用\(O(m)\)的时间求出答案,总复杂度\(O(nm)\)。模板题:洛谷4141
还需要知道可重集合的排列公式。即如果现在有\(k\)种元素,每种元素有\(a_i\)个,则该集合的排列计算公式是:
\]
言归正传
回到这道题。先考虑算出总合法方案数(即\(s_x=s_y\)的情况)。首先统计出每种恶棍的出现次数\(num[i]\)。设一种方案中前一半位置的恶棍种类组成集合\(S\)(即\(\sum_{i\in S} num[i]=\frac{n}{2}\)),则可以用背包DP算出\(S\)集合的方案数\(f[\frac{n}{2}]\)。然而,仅仅算出\(S\)集合的方案数是不够的,因为不同的排列被认为是不同的方案。根据上面的公式,前一半位置的排列方案数是:
\]
然后就不幸地发现,这个方案数跟具体选出了哪些集合有关……gg
但是……如果把两半合在一起考虑呢?当一半的\(S\)集合确定,另一半的种类集合\(S'\)也随之确定(设种类的全集为\(U\),则\(S\cap S'=\emptyset\)且\(S\cup S'=U\))。两半的方案数相乘是当\(S\)确定时的最终方案数,即:
\]
\(U\)是确定的,于是我们震惊地发现方案数与\(S\)无关……
所以,最终的答案就是:
\]
其中\(f[\frac{n}{2}]\)是背包DP算出的\(S\)集合的方案数。
现在,我们算出了总的合法方案数,即解决了询问\(s_x=s_y\)(相当于没有限制)的情况。开始考虑\(s_x\neq s_y\)的情况。设要求选到同一半的两种类型是\(a\)和\(b\)。此时不要想得太复杂(我刚写博客的时候都想得很复杂,写了很长一段然后删了233),这个限制只让上述\(S\)集合的方案数减少了。那一堆东西乘的不再是\(f[\frac{n}{2}]\),而是不用\(a\)和\(b\)两种类型(相当于两种物品)填满\(\frac{n}{2}\)的方案数再乘\(2\)(因为\(a\)和\(b\)既可能在前一半,也可能在后一半),直接做两次退背包即可。注意到\(|U|\)很小,最大只有\(52\),所以可以预处理每一对\(a\)和\(b\)的答案,每次需要\(O(n)\),总时间复杂度\(O(n|U|^2+q)\)。虽然算下来有\(2.7e8\),但是常数很小,加上Codeforces机器很快,所以可以过……
代码:
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cctype>
using namespace std;
namespace zyt
{
typedef long long ll;
const int N = 1e5 + 10, CH = 52, p = 1e9 + 7;
char str[N];
int f[N >> 1], g[N >> 1], h[N >> 1], cnt[CH][CH];
int num[CH], fac[N], finv[N];
int ctoi(const char c)
{
return isupper(c) ? c - 'A' + 26 : c - 'a';
}
inline int power(int a, int b)
{
int ans = 1;
while (b)
{
if (b & 1)
ans = (ll)ans * a % p;
a = (ll)a * a % p;
b >>= 1;
}
return ans;
}
inline int inv(const int a)
{
return power(a, p - 2);
}
inline void init()
{
fac[0] = 1;
for (int i = 1; i < N; i++)
fac[i] = (ll)fac[i - 1] * i % p;
finv[N - 1] = inv(fac[N - 1]);
for (int i = N - 1; i > 0; i--)
finv[i - 1] = (ll)finv[i] * i % p;
}
int work()
{
init();
scanf("%s", str);
int ans, len = strlen(str);
ans = (ll)fac[len >> 1] * fac[len >> 1] % p;
for (int i = 0; i < len; i++)
++num[ctoi(str[i])];
f[0] = 1;
for (int i = 0; i < CH; i++)
if (num[i])
{
ans = (ll)ans * finv[num[i]] % p;
for (int j = (len >> 1); j >= num[i]; j--)
f[j] = (f[j] + f[j - num[i]]) % p;
}
for (int i = 0; i < CH; i++)
if (num[i])
{
cnt[i][i] = f[len >> 1];
memcpy(g, f, sizeof(int[num[i]]));
for (int j = num[i]; j <= (len >> 1); j++)
g[j] = (f[j] - g[j - num[i]] + p) % p;
for (int j = i + 1; j < CH; j++)
if (num[j])
{
memcpy(h, g, sizeof(int[num[j]]));
for (int k = num[j]; k <= (len >> 1); k++)
h[k] = (g[k] - h[k - num[j]] + p) % p;
cnt[i][j] = cnt[j][i] = (ll)2LL * h[len >> 1] % p;
}
}
int q;
scanf("%d", &q);
while (q--)
{
int x, y;
scanf("%d%d", &x, &y);
printf("%lld\n", (ll)ans * cnt[ctoi(str[x - 1])][ctoi(str[y - 1])] % p);
}
return 0;
}
}
int main()
{
return zyt::work();
}
【Codeforces1111D_CF1111D】Destroy the Colony(退背包_组合数学)的更多相关文章
- Codeforces1111D Destroy the Colony 退背包+组合数
Codeforces1111D 退背包+组合数 D. Destroy the Colony Description: There is a colony of villains with severa ...
- Codeforces 1111D Destroy the Colony 退背包 (看题解)
第一次知道这种背包还能退的.... 我们用dp[ i ]表示选取若干个物品重量到达 i 的方案数. 如果我们g[ i ]表示不用第 x 个物品的, 然后选若干其他的物品到达 i 的方案数. if(i ...
- 01二重退背包+组合数学——cf1111d
退背包进阶,还是挺难想的 /* dp1[k]表示取到体积k的方案数 dp2[i][j][k]表示左侧必选ij的情况下,取到体积k的方案数 dp2[i][j][k]=dp1[k]-左侧不选ij的方案数 ...
- BZOJ_3398_[Usaco2009 Feb]Bullcow 牡牛和牝牛_组合数学
BZOJ_3398_[Usaco2009 Feb]Bullcow 牡牛和牝牛_组合数学 Description 约翰要带N(1≤N≤100000)只牛去参加集会里的展示活动,这些牛可以是牡牛, ...
- BZOJ_3129_[Sdoi2013]方程_组合数学+容斥原理
BZOJ_3129_[Sdoi2013]方程_组合数学+容斥原理 Description 给定方程 X1+X2+. +Xn=M 我们对第l..N1个变量进行一些限制: Xl < = A ...
- BZOJ_4517_[Sdoi2016]排列计数_组合数学
BZOJ_4517_[Sdoi2016]排列计数_组合数学 Description 求有多少种长度为 n 的序列 A,满足以下条件: 1 ~ n 这 n 个数在序列中各出现了一次 若第 i 个数 A[ ...
- BZOJ.2287.[POJ Challenge]消失之物(退背包)
BZOJ 洛谷 退背包.和原DP的递推一样,再减去一次递推就行了. f[i][j] = f[i-1][j-w[i]] + f[i-1][j] f[i-1][j] = f[i][j] - f[i-1][ ...
- [CF1111D]Destroy the Colony
题目大意:有一个长度为$n(n\leqslant10^5,n=0\pmod2)$的字符串,字符集大小为$52$,有$q(q\leqslant10^5)$次询问,每次询问第$x,y$个字符在这个字符串的 ...
- 51nod_1236_序列求和 V3 _组合数学
51nod_1236_序列求和 V3 _组合数学 Fib(n)表示斐波那契数列的第n项,Fib(n) = Fib(n-1) + Fib(n-2).Fib(0) = 0, Fib(1) = 1. (1, ...
随机推荐
- HDU4850 Wow! Such String! —— 字符串构造
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4850 代码如下: #include <iostream> #include <cst ...
- eclipse 卡死设置
都说eclipse比myeclipse小巧,但是 殊不知 用起来这么这么的卡,最后查资料,才知道是 配置给他的内存太 太小了,怪不得 他一直想着罢工呢. 在eclipse.ini文件中原来的配置如下: ...
- numpy.argmax 用在求解混淆矩阵用
numpy.argmax numpy.argmax(a, axis=None, out=None)[source] Returns the indices of the maximum values ...
- Dubbo原理与框架设计
Dubbo是常用的开源服务治理型RPC框架,在之前osgi框架下不同bundle之间的方法调用时用到过.其工作原理和框架设计值得开源技术爱好者学习和研究. 一.Dubbo的工作原理 调用关系说明 服务 ...
- 在WinDBG中查看调用栈的命令
命令 ========== k k命令显示的是一定数量的栈帧, 其中帧的数量是由.kframes命令来控制的, 默认值是256. kp 5 显示调用栈中前5个函数以及他们的参数. kb 5 显示调用栈 ...
- io_service work 的作用
当有任务的时候,run函数会一直阻塞:但当没有任务了,run函数会返回,所有异步操作终止. 客户端程序中,如果我想连接断开后重连,由于连接断开了,run会返回,当再次重连的时候,由于run返回了,即使 ...
- json : json数据解析(一)
在项目中经常用到json格式的数据转换与解析,先前写过一些小例子,现在整理下,以备后用和帮助后来者. 言归正传: 使用到的jar包 :json-lib-2.4-jdk15.jar,当然你也可以用自己版 ...
- could not get wglGetExtensionsStringARB
第一种解释: 现象: 启动应用程序时,在Emulator中,提示"could not get wglGetExtensionsStringARB". 原因分析: device sp ...
- HDFS源码分析四-HDFS Client
4. HDFS Client ( 未完待续 ) 目录: 4.1 认识 DFSClient ( 未完待续 ) 4.2 输入流 ( 未完待续 ) 4.3 输出流 ( 未完待续 ) 4.4 Distribu ...
- CF-807B
B. T-Shirt Hunt time limit per test 2 seconds memory limit per test 256 megabytes input standard inp ...