[CF1111D]Destroy the Colony
题目大意:有一个长度为$n(n\leqslant10^5,n=0\pmod2)$的字符串,字符集大小为$52$,有$q(q\leqslant10^5)$次询问,每次询问第$x,y$个字符在这个字符串的同一侧,并且所有相同字符在字符串的同一侧的方案数。
题解:因为字符集大小只有$52$,所以本质不同的询问只有$52\times52$种,预处理。
发现若确定了左右各放那几种字符后方案数是一定的,为$\dfrac{\left(\dfrac n2!\right)^2}{\prod\limits_{i=1}^{52}cnt_i!}$,$cnt_i$表示字符$i$出现次数。只需要求出左边可以放的字符种类,乘上这个数就是答案。
考虑$DP$,若正常的做,不加入$x,y$两种字符,复杂度是$O(52^3\times n)$,不可以通过。发现最多只有两种字符不加入,可以退背包,就倒着做背包部分即可,复杂度$O(52^2\times n)$
卡点:阶乘逆元算成了每个数的逆元
C++ Code:
#include <algorithm>
#include <cctype>
#include <cstdio>
#include <iostream>
#define maxn 100010
#define N 52
const int mod = 1e9 + 7;
inline void reduce(int &x) { x += x >> 31 & mod; } std::string __s;
long long C;
int n, nn, q;
int fac[maxn], inv[maxn];
int s[maxn], cnt[N]; int f[maxn], g[maxn], ans[N][N];
int solve(int x, int y) {
std::copy(f, f + nn + 1, g);
for (int i = cnt[x]; i <= nn; ++i) reduce(g[i] -= g[i - cnt[x]]);
for (int i = cnt[y]; i <= nn; ++i) reduce(g[i] -= g[i - cnt[y]]);
return 2 * g[nn] % mod;
}
int main() {
std::ios::sync_with_stdio(false), std::cin.tie(0), std::cout.tie(0);
std::cin >> __s; n = __s.length(), nn = n >> 1;
for (int i = 0; i < n; ++i) {
s[i + 1] = islower(__s[i]) ? __s[i] - 'a' : __s[i] - 'A' + 26;
++cnt[s[i + 1]];
}
fac[0] = fac[1] = inv[0] = inv[1] = 1;
for (int i = 2; i <= nn; ++i) {
fac[i] = static_cast<long long> (fac[i - 1]) * i % mod;
inv[i] = static_cast<long long> (mod - mod / i) * inv[mod % i] % mod;
}
for (int i = 2; i <= nn; ++i) inv[i] = static_cast<long long> (inv[i - 1]) * inv[i] % mod;
C = static_cast<long long> (fac[nn]) * fac[nn] % mod;
for (int i = 0; i < N; ++i) C = C * inv[cnt[i]] % mod; f[0] = 1;
for (int i = 0; i < N; ++i) if (cnt[i])
for (int j = nn; j >= cnt[i]; --j) reduce(f[j] += f[j - cnt[i]] - mod);
for (int i = 0; i < N; ++i) if (cnt[i]) {
for (int j = i + 1; j < N; ++j) if (cnt[j])
ans[i][j] = ans[j][i] = solve(i, j);
ans[i][i] = f[nn];
} std::cin >> q;
while (q --> 0) {
static int x, y;
std::cin >> x >> y; x = s[x], y = s[y];
std::cout << C * ans[x][y] % mod << '\n';
}
return 0;
}
[CF1111D]Destroy the Colony的更多相关文章
- Codeforces1111D Destroy the Colony 退背包+组合数
Codeforces1111D 退背包+组合数 D. Destroy the Colony Description: There is a colony of villains with severa ...
- [CF1111D] Destory the Colony
Portal 大致题意: 给定一个偶数长度(\(n \leq 10 ^ 5\))的字符串, 只包含大小写字母. 有q(\(q \leq 10 ^ 5\))次询问, 每次指定两个位置, 要求通过交换字符 ...
- 【Codeforces1111D_CF1111D】Destroy the Colony(退背包_组合数学)
题目: Codeforces1111D 翻译: [已提交至洛谷CF1111D] 有一个恶棍的聚居地由几个排成一排的洞穴组成,每一个洞穴恰好住着一个恶棍. 每种聚居地的分配方案可以记作一个长为偶数的字符 ...
- Codeforces 1111D Destroy the Colony 退背包 (看题解)
第一次知道这种背包还能退的.... 我们用dp[ i ]表示选取若干个物品重量到达 i 的方案数. 如果我们g[ i ]表示不用第 x 个物品的, 然后选若干其他的物品到达 i 的方案数. if(i ...
- Destroy the Colony CodeForces - 1111D (可逆背包,计数)
大意:给定字符串$s$, 保证长度为偶数, 给定q个询问, 每次询问给定两个位置$x$,$y$, 可以任意交换字符, 要求所有字符$s[x],s[y]$在同一半边, 剩余所有同种字符在同一半边的方案数 ...
- CF - 1111D Destroy the Colony DP
题目传送门 题意: 这个题目真的是最近遇到的最难读. 有一个长度n的字符串,每一位字符都代表的是该种种类的敌人. 现在如果一个序列合法的话,就是同一种种类的敌人都在字符串的左半边或者右半边. 现在有q ...
- codeforces选做
收录了最近本人完成的一部分codeforces习题,不定期更新 codeforces 1132E Knapsack 注意到如果只使用某一种物品,那么这八种物品可以达到的最小相同重量为\(840\) 故 ...
- CodeCraft-19 and Codeforces Round #537 (Div. 2) 题解
传送门 D. Destroy the Colony 首先明确题意:除了规定的两种(或一种)字母要在同侧以外,其他字母也必须在同侧. 发现当每种字母在左/右边确定之后,方案数就确定了,就是分组的方案数乘 ...
- 退役前的最后的做题记录upd:2019.04.04
考试考到自闭,每天被吊打. 还有几天可能就要AFO了呢... Luogu3602:Koishi Loves Segments 从左向右,每次删除右端点最大的即可. [HEOI2014]南园满地堆轻絮 ...
随机推荐
- 微信小程序:页面跳转时传递数据到另一个页面
一.功能描述 页面跳转时,同时把当前页面的数据传递给跳转的目标页面,并在跳转后的目标页面进行展示 二.功能实现 1. 代码实现 test1页面 // pages/test1/test1.js Page ...
- spark读取mongodb数据写入hive表中
一 环境: spark-: hive-; scala-; hadoop--cdh-; jdk-1.8; mongodb-2.4.10; 二.数据情况: MongoDB数据格式{ "_i ...
- angular之$watch() $watchGroup()和$watchCollection()
$watch $watch主要是用来监听一个对象,在对象发生变化时触发某个事件. 用法: $scope.$watch(watchFn,watchAction, deepWatch) 接下来讲一下这几个 ...
- c++编译器处理 函数返回值
X bar() { X xx; return xx; } // compiler generated temporary X __temp0; ( bar( __temp0 ), __temp0 ). ...
- kobject和kset的一些学习心得
#include <linux/module.h> #include <linux/kernel.h> #include <linux/kobject.h> #in ...
- Python小白学习之基础知识(个人笔记)
介绍while else的使用,这个不常用 格式化输出 while esle ,当循环内有break语句时,不执行else语句,当没有break语句时,执行完while循环,然后执行else下面的语句 ...
- selenium webdriver API详解(三)
本系列主要讲解webdriver常用的API使用方法(注意:使用前请确认环境是否安装成功,浏览器驱动是否与谷歌浏览器版本对应) 一:获取页面元素的文本内容:text 例:获取我的博客名字文本内容 代码 ...
- katalon系列十三:5.10新增跳过用例&命令行赋值全局变量
Katalon Studio升级到5.10版本了,这次新增了2个很实用的功能:一.跳过用例在Listener中新增了跳过用例方法,Listener类似于JUnit4的annotation中的@Befo ...
- Animator & Timeline
using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.Pla ...
- idea scala 报 with UTF-8 Please try specifying another one using the -encoding option
现象如下图, 代码里有汉字,执行代码报错,说编码格式不对, 修改方式如上面,将右下角的编码格式修改成 u8即可.