01二重退背包+组合数学——cf1111d
退背包进阶,还是挺难想的
/*
dp1[k]表示取到体积k的方案数
dp2[i][j][k]表示左侧必选ij的情况下,取到体积k的方案数
dp2[i][j][k]=dp1[k]-左侧不选ij的方案数
但是这样比较难搞,我们把状态转换一下,dp2[i][j][k]表示左侧不选i,j,取到k的方案数
这样要两层退背包来解决
状态前两维可以直接压缩,用ans[i][j]来保存答案,复杂度O(52*52*n)
*/
#include<bits/stdc++.h>
using namespace std;
#define maxn 200005
#define ll long long
#define mod 1000000007
ll f[maxn],inv[maxn],invf[maxn];
void init(){
f[]=inv[]=invf[]=invf[]=;
for(int i=;i<maxn;i++)
inv[i]=(mod-mod/i)*inv[mod%i]%mod;
for(int i=;i<maxn;i++){
f[i]=f[i-]*i%mod;
invf[i]=invf[i-]*inv[i]%mod;
}
} char s[maxn];
ll cnt[],n,C;
ll dp1[maxn],dp2[maxn],dp3[maxn],ans[][];
void work(){
//先处理背包
dp1[]=;
for(int i=;i<;i++)
if(cnt[i])
for(int j=n/;j>=cnt[i];j--)
dp1[j]=(dp1[j]+dp1[j-cnt[i]])%mod;
for(int i=;i<;i++)
if(cnt[i]){
//先退去一层:没有底i个物品时的状态dp2
memset(dp2,,sizeof dp2);
for(int k=;k<=n/;k++)
if(k<cnt[i]) dp2[k]=dp1[k];
else dp2[k]=(dp1[k]-dp2[k-cnt[i]]+mod)%mod;
ans[i][i]=dp2[n/]; for(int j=;j<;j++)
if(j!=i && cnt[j]){
//再退一层背包
memset(dp3,,sizeof dp3);
for(int k=;k<=n/;k++)
if(k<cnt[j])dp3[k]=dp2[k];
else dp3[k]=(dp2[k]-dp3[k-cnt[j]]+mod)%mod;
ans[i][j]=ans[j][i]=dp3[n/];
}
}
} int main(){
init();
scanf("%s",s);
n=strlen(s);
for(int i=;i<n;i++){
if(s[i]<='Z' && s[i]>='A')
cnt[s[i]-'A']++;
else cnt[s[i]-'a'+]++;
} C=*f[n/]*f[n/]%mod;
for(int i=;i<;i++)
C=C*invf[cnt[i]]%mod; work(); int q;cin>>q;
while(q--){
char a,b;int c,d;
scanf("%d %d",&c,&d);
a=s[c-],b=s[d-];
if(a<='Z' && a>='A')
c=a-'A';
else c=a-'a'+;
if(b<='Z' && b>='A')
d=b-'A';
else d=b-'a'+; cout<<ans[c][d]*C%mod<<'\n';
}
}
01二重退背包+组合数学——cf1111d的更多相关文章
- 【Codeforces1111D_CF1111D】Destroy the Colony(退背包_组合数学)
题目: Codeforces1111D 翻译: [已提交至洛谷CF1111D] 有一个恶棍的聚居地由几个排成一排的洞穴组成,每一个洞穴恰好住着一个恶棍. 每种聚居地的分配方案可以记作一个长为偶数的字符 ...
- 01退背包——bzoj2287
退背包就是限制某一件物品不可取的方案数 先做出无限制的方案数,然后对于当前不可取的物品,dp2[j]表示不取改物品情况下,取得体积为j的方案数 有状态方程 dp2[j]=dp1[j]-dp2[j-w[ ...
- 01二维背包+bitset优化——hdu5890
口胡一种别的解法: 三重退背包,g1[j]k]表示不选x的选了j件物品,体积为k的方案数,g[0][0] = 1 , g1[j][k]=dp[j][k]-g1[j-1][k-a[x]] 然后按这样再退 ...
- luogu 4377 Talent show 01分数规划+背包dp
01分数规划+背包dp 将分式下面的部分向右边挪过去,通过二分答案验证, 注意二分答案中如果验证的mid是int那么l=mid+1,r=mid-1,double类型中r=mid,l=mid; 背包dp ...
- 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][ ...
- Codeforces 1111D(退背包、排列组合)
要点 优质题解 因为只有某type坏人全部分布在同一撇时,才能一次消灭.所以题目安排完毕后一定是type(x)和type(y)占一半,其余占另一半. 实际情况只有52*52种,则预处理答案 枚举某两种 ...
- Codeforces1111D Destroy the Colony 退背包+组合数
Codeforces1111D 退背包+组合数 D. Destroy the Colony Description: There is a colony of villains with severa ...
- 01二维背包——poj2576
/* 要求把a数组分成两个集合,两个集合人数最多差1,并且元素之和的差尽可能小 那只要把所有可行的列出来即可 01二维背包,即体积是个二维数据,那么我们的背包状态也应该设为二维 dp[j][k]设为 ...
- Codeforces 1111D Destroy the Colony 退背包 (看题解)
第一次知道这种背包还能退的.... 我们用dp[ i ]表示选取若干个物品重量到达 i 的方案数. 如果我们g[ i ]表示不用第 x 个物品的, 然后选若干其他的物品到达 i 的方案数. if(i ...
随机推荐
- Java对象什么时候可以被垃圾回收?JVM的永久代中会发生垃圾回收么?
当对象对当前使用这个对象的应用程序变得不可触及的时候,这个对象就可以被回收了.垃圾回收不会发生在永久代,如果永久代满了或者是超过了临界值,会触发完全垃圾回收(Full GC).如果你仔细查看垃圾收集器 ...
- 转帖---把eclipse默认的编译文件夹build改为web-inf/classess文件夹
1.在web-info下新奸classess文件夹 2.右键项目 3.选择java build path ————————————
- 如何基于 Nacos 和 Sentinel ,实现灰度路由和流量防护一体化
基于Alibaba Nacos和Sentinel,实现灰度路由和流量防护一体化的解决方案,发布在最新的 Nepxion Discovery 5.4.0 版,具体参考: 源码主页,请访问 源码主页指南主 ...
- Flex布局(二)
接上一篇,说一下flex布局的实例,转自阮一峰老师的博客
- Android项目中引用到其他工程
有的时候我们需要在现有的项目中引用到其他项目的资源和文件,当然我们可以将被引用的工程打成jar包,但是这有个缺点就是,这个改动比较麻烦,除非是被引用的工程的资源和源程序文件不再改动,可以这样做,否则每 ...
- Linux 软硬链接区别
一.“硬链接“和“软链接“ 链接的概念:链接简单说实际上是一种文件共享的方式,是 POSIX 中的概念,主流文件系统都支持链接文件. 链接的作用:可以将链接简单地理解为 Windows 中常见的快捷方 ...
- spark面试问题收集
spark面试问题 1.spark中的RDD是什么,有哪些特性 RDD(Resilient Distributed Dataset)叫做弹性分布式数据集,是Spark中最基本的数据抽象,它代表一个不可 ...
- Tomcat服务器配置参考
Coyote HTTP/1.1 Connector 概述 Coyote HTTP/1.1 Connector元素是一个支持HTTP/1.1协议的Connector组件.它使Catalina除了能够执行 ...
- fatal error C1189: #error : "No Target Architecture" 解决办法一
在编译程序的时候发现报这个错误,在网上看到很多文章,说设置include路径,lib目录等等,都没有解决.最后调整了以下include文件的顺序,问题解决了.例如 从头文件a.h中截取的一段 type ...
- 2019杭电多校第四场hdu6621 K-th Closest Distance(二分答案+主席树)
K-th Closest Distance 题目传送门 解题思路 二分答案+主席树 先建主席树,然后二分答案mid,在l和r的区间内查询[p-mid, p+mid]的范围内的数的个数,如果大于k则说明 ...