CF - 1111D Destroy the Colony DP
题意:
这个题目真的是最近遇到的最难读。
有一个长度n的字符串,每一位字符都代表的是该种种类的敌人。
现在如果一个序列合法的话,就是同一种种类的敌人都在字符串的左半边或者右半边。
现在有q次询问,现在问你将 s[x] 和 s[y] 的敌人都放在同一边的合法方案数是多少。
题解:
首先如果划分组之后,那么答案就是,m! * m! * 2/ (c1! * c2! * c3! .... )
然后对于每一组来说就是 这个值是一定的。
然后就是需要求这个分组方案数。
对于分组方案数,可以通过背包来求这个方案数是多少。
但是如果枚举每个同类的字符,那么最后的复杂度是52 * 52 * 52 * n。
所以可以将总方案数先算出来,然后再将x,y的方案数,从里面删除,删除之后,不含x,y的方案数,相当于含了x,y的方案数。 这个复杂度是52*52*n。
代码:
/*
code by: zstu wxk
time: 2019/02/07
*/
#include<bits/stdc++.h>
using namespace std;
#define Fopen freopen("_in.txt","r",stdin); freopen("_out.txt","w",stdout);
#define LL long long
#define ULL unsigned LL
#define fi first
#define se second
#define pb push_back
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define lch(x) tr[x].son[0]
#define rch(x) tr[x].son[1]
#define max3(a,b,c) max(a,max(b,c))
#define min3(a,b,c) min(a,min(b,c))
typedef pair<int,int> pll;
const int inf = 0x3f3f3f3f;
const int _inf = 0xc0c0c0c0;
const LL INF = 0x3f3f3f3f3f3f3f3f;
const LL _INF = 0xc0c0c0c0c0c0c0c0;
const LL mod = (int)1e9+;
const int N = 1e5 + ;
int cnt[N];
char s[N];
LL ans[][];
int F[N], Finv[N], inv[N];/// F是阶层 Finv是逆元的阶层
void init(){
inv[] = ;
for(int i = ; i < N; i++)
inv[i] = (mod - mod/i) * 1ll * inv[mod % i] % mod;
F[] = Finv[] = ;
for(int i = ; i < N; i++){
F[i] = F[i-] * 1ll * i % mod;
Finv[i] = Finv[i-] * 1ll * inv[i] % mod;
}
}
int comb(int n, int m){ /// C(n,m)
if(m < || m > n) return ;
return F[n] * 1ll * Finv[n-m] % mod * Finv[m] % mod;
}
int id(char ch){
if(islower(ch)) return ch - 'a' + ;
return ch - 'A' + ;
}
int dp[N], tp[N];
void Ac(){
int n = strlen(s+);
int m = n / ;
for(int i = ; i <= n; ++i)
++cnt[id(s[i])];
dp[] = ;
for(int i = ; i <= ; ++i){
if(cnt[i]){
for(int j = m; j >= cnt[i]; --j)
dp[j] = (dp[j] + dp[j-cnt[i]]) % mod;
}
}
for(int i = ; i <= m; ++i)
tp[i] = dp[i];
for(int i = ; i <= ; ++i){
if(cnt[i] && cnt[i] <= m){
for(int j = cnt[i]; j <= m; ++j){
dp[j] = (dp[j] - dp[j-cnt[i]] + mod) % mod;
}
ans[i][i] = dp[m];
for(int j = ; j <= ; ++j){
if(cnt[j] && cnt[j] <= m && j != i){
for(int k = cnt[j]; k <= m; ++k){
dp[k] = (dp[k] - dp[k-cnt[j]] + mod)%mod;
}
ans[i][j] = dp[m];
for(int k = m; k >= cnt[j]; --k){
dp[k] = (dp[k] + dp[k-cnt[j]]) % mod;
}
}
}
for(int j = m; j >= cnt[i]; --j)
dp[j] = tp[j];
}
}
LL zz = 2ll * F[m] * F[m] % mod;
for(int i = ; i <= ; ++i)
zz = (zz * Finv[cnt[i]]) % mod;
int q, x, y;
scanf("%d", &q);
while(q--){
scanf("%d%d", &x, &y);
printf("%I64d\n", zz * ans[id(s[x])][id(s[y])] % mod);
}
return ;
}
int main(){
init();
while(~scanf("%s", s+)){
Ac();
}
return ;
}
CF - 1111D Destroy the Colony DP的更多相关文章
- Codeforces 1111D Destroy the Colony 退背包 (看题解)
第一次知道这种背包还能退的.... 我们用dp[ i ]表示选取若干个物品重量到达 i 的方案数. 如果我们g[ i ]表示不用第 x 个物品的, 然后选若干其他的物品到达 i 的方案数. if(i ...
- Codeforces1111D Destroy the Colony 退背包+组合数
Codeforces1111D 退背包+组合数 D. Destroy the Colony Description: There is a colony of villains with severa ...
- CF 983B XOR-pyramid(区间dp,异或)
CF 983B XOR-pyramid(区间dp,异或) 若有一个长度为m的数组b,定义函数f为: \(f(b) = \begin{cases} b[1] & \quad \text{if } ...
- Destroy the Colony CodeForces - 1111D (可逆背包,计数)
大意:给定字符串$s$, 保证长度为偶数, 给定q个询问, 每次询问给定两个位置$x$,$y$, 可以任意交换字符, 要求所有字符$s[x],s[y]$在同一半边, 剩余所有同种字符在同一半边的方案数 ...
- CF 9D. How many trees?(dp)
题目链接 以前做过类似的,USACO,2.3,开始数组开小了,导致数据乱了,然后超数据范围了,.. #include <cstdio> #include <iostream> ...
- CF 346B. Lucky Common Subsequence(DP+KMP)
这题确实很棒..又是无想法..其实是AC自动机+DP的感觉,但是只有一个串,用kmp就行了. dp[i][j][k],k代表前缀为virus[k]的状态,len表示其他所有状态串,处理出Ac[len] ...
- CF 55D. Beautiful numbers(数位DP)
题目链接 这题,没想出来,根本没想到用最小公倍数来更新,一直想状态压缩,不过余数什么的根本存不下,看的von学长的blog,比着写了写,就是模版改改,不过状态转移构造不出,怎么着,都做不出来. #in ...
- CF 149D Coloring Brackets 区间dp ****
给一个给定括号序列,给该括号上色,上色有三个要求 1.只有三种上色方案,不上色,上红色,上蓝色 2.每对括号必须只能给其中的一个上色 3.相邻的两个不能上同色,可以都不上色 求0-len-1这一区间内 ...
- cf 547B. Mike and Feet dp
题意: n个矩阵排成一排,n<=2e5,高度分别为hei[i],宽度为1 对于一些连续的矩阵,矩阵的size为矩阵的个数,矩阵的strength为这些矩阵中高度最低的那一个高度 求:for ea ...
随机推荐
- 章节十五、3-对象仓库、Page Factory实例应用
一.如何创建对象仓库 package pageclasses; import org.openqa.selenium.WebDriver; import org.openqa.selenium.Web ...
- WeihanLi.Npoi 导出支持自定义列内容啦
WeihanLi.Npoi 导出支持自定义列内容啦 Intro 之前也有网友给提出过希望列合并或者自定义列内容的 issue 或请求,起初因为自己做 WeihanLi.Npoi 这个扩展的最初目的是导 ...
- Github上fork的项目如何merge原Git项目
问题场景 小明在Github上fork了一个大佬的项目,并clone到本地开发一段时间,再提交merge request到原Git项目,过了段时间,原作者联系小明,扔给他下面这幅截图并告知合并处理冲突 ...
- React进阶之路书籍笔记
React进阶之路: "于复合类型的变量,变量名不指向数据,而是指向数据所在的地址.const命令只是保证变量名指向的地址不变,并不保证该地址的数据不变,所以将一个对象声明为常量必须非常小心 ...
- python_0基础学习_day01
Python是一门动态解释型的强类型定义语言 一.变量 变量命名规则 由数字.字母.下划线组成 不能以数字开头 要具有描述性 要区分大小写 禁止使用python的关键字(在pycharm中关键字明明变 ...
- Java匹马行天下之J2EE框架开发——Spring—>用IDEA开发Spring程序(01)
一.心动不如行动 一.创建项目 *注:在IDEA中我创建的Maven项目,不了解Maven的朋友可以看我之前的博客“我们一起走进Maven——知己知彼”,了解Maven后可以看我之前的博客“Maven ...
- 完全零基础在Linux中安装 JDK
完全零基础在Linux中安装 JDK 总体思路:先确定没有Java程序了 — 然后创建相应路径文件夹 — 下载JDK — 解压到当前路径 — 自定义文件名称 — 配置环境变量 — 检查是否安装成功 第 ...
- 映射&集合
哈希函数 通过哈希表可以实现 O(1) 复杂度的查找. 哈希函数构造方法:设计好的哈希函数的两个基本原则,计算简单+分布均匀 1. 直接定址法 用key自身的某个线性函数来定址,f(key) = a* ...
- 【CodeForces - 1200A】Hotelier(水题、模拟)
Hotelier 直接翻译了 Descriptions Amugae的酒店由10人组成10客房.房间从0开始编号0到99 从左到右. 酒店有两个入口 - 一个来自左端,另一个来自右端.当顾客通过左入口 ...
- JS扫雷小游戏
HTML代码 <title> 扫雷 </title> <!-- ondragstart:防拖拽生成新页面 oncontextmenu:屏蔽右键菜单--> <b ...