题目传送门

题意:

这个题目真的是最近遇到的最难读。

有一个长度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的更多相关文章

  1. Codeforces 1111D Destroy the Colony 退背包 (看题解)

    第一次知道这种背包还能退的.... 我们用dp[ i ]表示选取若干个物品重量到达 i 的方案数. 如果我们g[ i ]表示不用第 x 个物品的, 然后选若干其他的物品到达 i 的方案数. if(i ...

  2. Codeforces1111D Destroy the Colony 退背包+组合数

    Codeforces1111D 退背包+组合数 D. Destroy the Colony Description: There is a colony of villains with severa ...

  3. CF 983B XOR-pyramid(区间dp,异或)

    CF 983B XOR-pyramid(区间dp,异或) 若有一个长度为m的数组b,定义函数f为: \(f(b) = \begin{cases} b[1] & \quad \text{if } ...

  4. Destroy the Colony CodeForces - 1111D (可逆背包,计数)

    大意:给定字符串$s$, 保证长度为偶数, 给定q个询问, 每次询问给定两个位置$x$,$y$, 可以任意交换字符, 要求所有字符$s[x],s[y]$在同一半边, 剩余所有同种字符在同一半边的方案数 ...

  5. CF 9D. How many trees?(dp)

    题目链接 以前做过类似的,USACO,2.3,开始数组开小了,导致数据乱了,然后超数据范围了,.. #include <cstdio> #include <iostream> ...

  6. CF 346B. Lucky Common Subsequence(DP+KMP)

    这题确实很棒..又是无想法..其实是AC自动机+DP的感觉,但是只有一个串,用kmp就行了. dp[i][j][k],k代表前缀为virus[k]的状态,len表示其他所有状态串,处理出Ac[len] ...

  7. CF 55D. Beautiful numbers(数位DP)

    题目链接 这题,没想出来,根本没想到用最小公倍数来更新,一直想状态压缩,不过余数什么的根本存不下,看的von学长的blog,比着写了写,就是模版改改,不过状态转移构造不出,怎么着,都做不出来. #in ...

  8. CF 149D Coloring Brackets 区间dp ****

    给一个给定括号序列,给该括号上色,上色有三个要求 1.只有三种上色方案,不上色,上红色,上蓝色 2.每对括号必须只能给其中的一个上色 3.相邻的两个不能上同色,可以都不上色 求0-len-1这一区间内 ...

  9. cf 547B. Mike and Feet dp

    题意: n个矩阵排成一排,n<=2e5,高度分别为hei[i],宽度为1 对于一些连续的矩阵,矩阵的size为矩阵的个数,矩阵的strength为这些矩阵中高度最低的那一个高度 求:for ea ...

随机推荐

  1. 【Android】Android sdk content loader 0%

    前天用 Eclipse 突然遇到了这个问题...重启了好几次都不行,百度了一下,原来之前有不少人遇到过.后来找到了一篇文章,其中的方法二(如下): 方法二(关闭后,拔网线再重启): 如果用最省事的方法 ...

  2. 【iOS】iOS viewDidLoad 方法名问题

    这两天在调试一个项目,跳转到一个页面的时候总是不显示标题栏(当然也没有标题栏的返回按钮),搞了好久,今天总算找到了问题:之前的开发人员竟然把 viewDidLoad 这个基本的方法名写成了 views ...

  3. Qt实现表格树控件-自绘树节点虚线

    目录 一.开心一刻 二.自绘树节点? 三.效果展示 四.实现思路 1.可扩展接口 2.函数重写 3.同步左侧表头 五.相关文章 原文链接:Qt实现表格树控件-自绘树节点虚线 一.开心一刻 一程序员第一 ...

  4. 史上最全面的SignalR系列教程-1、认识SignalR

    SignalR 是什么? SignalR 是一个面向 ASP.NET 开发人员的库,可简化将实时 web 功能添加到应用程序的过程. 实时 web 功能是让服务器代码将内容推送到连接的客户端立即可用, ...

  5. LR(1)语法分析器生成器(生成Action表和Goto表)java实现(二)

    本来这次想好好写一下博客的...结果耐心有限,又想着烂尾总比断更好些.于是还是把后续代码贴上.不过后续代码是继续贴在BNF容器里面的...可能会显得有些臃肿.但目前管不了那么多了.先贴上来吧hhh.说 ...

  6. JAVA基础知识(二):List接口、ArrayList类和LinkedList类

    List接口继承了Collection接口,位于java.util包中.它包含Collection接口的所有方法,外加其他一些方法(具体实现参考源码),比较重要的有: anyType get(int ...

  7. DT-06 For Homekit

    一. 配置DT-06上网 连接此热点,会自动弹出wifi配置页面. 输入选中的路由密码,点 Join加入,如果路由没有出现在列表中,点 Other手工输入(仅支持2.4g路由配置) 二.配置dt-06 ...

  8. 垂直渐变的Button

    public partial class RoundButton : Button { Rectangle r; private Brush _myBrush = null; , , ); , , ) ...

  9. 构建docker虚拟化平台

    安装epel-release扩展包 yum install epel-release -y 安装docker yum install docker-ce 启动docker systemctl star ...

  10. 关于selenium自动化对iframe内嵌元素的处理

    今天上班闲来无聊,于是来练练自动化,结果碰上了可恶的iframe,楼主,以前也遇到过,但是一直也没搞懂怎么处理的,都是抄别人的代码,今天决定独立解决试试.首先先来认识什么是iframe,它就长下图这样 ...