全网唯一一篇容斥题解

Description

Solution

看到这个题,大部分人想的是状压dp

但是我是个蒟蒻没想到,就用容斥切掉了。

并且复杂度比一般状压低,

(其实这个容斥的算法,提出来源于ywy_c_asm)

(然而我知道了这个算法,竟然和他写的不一样,而且比他跑的快)

进入正题:

我们需要统计恰好满足匹配k个的情况。

那么,我们可以先找出来,恰好满足n个,n-1,n-2。。。k个的情况。

分别记为ans[i]

ans[i]怎么算呢?

先给出公式:

ans[i]=cal(i)-∑C(j,i)×ans[j] 其中,i+1<=j<=n

cal(i)表示,从n个中任意选择i个,对于所有选择的情况,的方案数的和。

cal(i)可以dfs暴力C(n,i)枚举,每次统计答案。计入tot

void dfs(int x,int has){
if(x==n+){
if(has!=up) return;
ll lp=;
for(int j=;j<=len;j++){
las=-;
for(int i=;i<=up;i++){
if(a[mem[i]][j]!='?'){
if(las==-){
las=a[mem[i]][j]-'a';
}
else if(las!=a[mem[i]][j]-'a') return;
}
}
if(las==-)lp=(lp*)%mod;
}
(tot+=lp)%=mod;
return;
}
if(has<up) {
mem[++cnt]=x;
dfs(x+,has+);
mem[cnt--]=;
}
if(n-x>=up-has) dfs(x+,has);
}

至于后面减去的部分。就是容斥的内容了。

大家可以自己画一个韦恩图理解一下。

这里有一个例子:n=4

现在我们要算ans[2],也就是恰好匹配2个的T的方案数

就是黄色的部分。

红色的数字是这个区域被算cal(i)的次数。

可见,三个点的重复区域,由于有C(3,2)种方法选到,所以会被算C(3,2)次。

所以减去所有的ans[3]即可。

其他情况同理。

最后输出ans[1]

组合数打表。

理论复杂度:
O(n×len×2^15)

Code

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=;
const int M=;
const int mod=;
char a[N][M];
int len;
int n,t,k;
int mem[N],cnt;
ll ans[N];
ll c[N][N];
ll sum;
ll tot;//tot measures
int up;//choose
int las;
void dfs(int x,int has){//dfs计算tot
if(x==n+){
if(has!=up) return;
ll lp=;
for(int j=;j<=len;j++){
las=-;
for(int i=;i<=up;i++){
if(a[mem[i]][j]!='?'){
if(las==-){
las=a[mem[i]][j]-'a';
}
else if(las!=a[mem[i]][j]-'a') return;//两个字符不一样,无合法方案
}
}
if(las==-)lp=(lp*)%mod;//如果都是‘?’可以随便填,否则只有一种
}
(tot+=lp)%=mod;
return;
}
if(has<up) {
mem[++cnt]=x;
dfs(x+,has+);
mem[cnt--]=;
}
if(n-x>=up-has) dfs(x+,has);
} void clear(){
memset(ans,,sizeof ans);
sum=;
len=;
}
int main()
{
for(int i=;i<=N-;i++){
c[i][]=;
for(int j=;j<=i;j++){
c[i][j]=(c[i-][j-]+c[i-][j])%mod;
}
}
scanf("%d",&t);
while(t--){
clear();//清空数组,其实没有必要
scanf("%d%d",&n,&k);
for(int i=;i<=n;i++){
scanf("%s",a[i]+);
}
len=strlen(a[]+);//长度 for(int i=n;i>=k;i--){//ans[i]计算
tot=;up=i;
dfs(,);
sum=;
for(int j=i+;j<=n;j++){//容斥的处理
(sum+=c[j][i]*ans[j])%=mod;
}
ans[i]=(tot-sum+mod)%mod;
}
printf("%lld\n",ans[k]);
}
return ;
}

[SDOI2009]Bill的挑战——全网唯一 一篇容斥题解的更多相关文章

  1. [BZOJ3523][Poi2014]KLO-Bricks——全网唯一 一篇O(n)题解+bzoj最优解

    Description 有n种颜色的砖块,第i种颜色的砖块有a[i]个,你需要把他们放成一排,使得相邻两个砖块的颜色不相同,限定第一个砖块的颜色是start,最后一个砖块的颜色是end,请构造出一种合 ...

  2. 【BZOJ1879】[SDOI2009]Bill的挑战(动态规划)

    [BZOJ1879][SDOI2009]Bill的挑战(动态规划) 题面 BZOJ 洛谷 题解 本来还想着容斥来着,这个数据范围直接暴力就好.设\(f[i][S]\)表示当前填到了第\(i\)位,和\ ...

  3. bzoj千题计划207:bzoj1879: [Sdoi2009]Bill的挑战

    http://www.lydsy.com/JudgeOnline/problem.php?id=1879 f[i][j] 表示匹配了i个字符,匹配字符串的状态为j的方案数 枚举下一个字符是什么 计算加 ...

  4. 【BZOJ1879】[Sdoi2009]Bill的挑战 状压DP

    [BZOJ1879][Sdoi2009]Bill的挑战 Description Input 本题包含多组数据.  第一行:一个整数T,表示数据的个数.  对于每组数据:  第一行:两个整数,N和K(含 ...

  5. bzoj 1879: [Sdoi2009]Bill的挑战

    题目链接 bzoj 1879: [Sdoi2009]Bill的挑战 题解 n<=15,装压吧 对所有字符串进行装压 可以预处理一个数组can[i][j]表示所有的字符串中,有哪些可以在第i位匹配 ...

  6. [bzoj1879][Sdoi2009]Bill的挑战_动态规划_状压dp

    Bill的挑战 bzoj-1879 Sdoi-2009 题目大意: 注释:$1\le t \le 5$,$1\le m \le 15$,$1\le length \le 50$. 想法: 又是一个看数 ...

  7. [LuoguP2167][SDOI2009]Bill的挑战_容斥原理/状压dp

    Bill的挑战 题目链接:https://www.luogu.org/problem/P2167 数据范围:略. 题解: 因为$k$特别小,想到状压. 状压的方式也非常简单,就是暴力枚举. 但是会不会 ...

  8. 【[SDOI2009]Bill的挑战】

    一看题解好像全是状压DP,那么我就来补充一个容斥写法吧 乍一看,好像是水题,枚举选哪k个串,然后判断 1,如果这k个串中至少两个串某位置确定且不相同,答案显然为02,如果这个位置只被有且仅有一个串确定 ...

  9. bzoj 1879 [Sdoi2009]Bill的挑战(状压DP)

    Description  Input 本题包含多组数据. 第一行:一个整数T,表示数据的个数. 对于每组数据: 第一行:两个整数,N和K(含义如题目表述). 接下来N行:每行一个字符串. Output ...

随机推荐

  1. UWP ListView 绑定 单击 选中项 颜色

    refer: https://www.cnblogs.com/lonelyxmas/p/7650259.html using System; using System.Collections.Gene ...

  2. 20155209 林虹宇 Exp9 Web安全基础

    Exp9 Web安全基础 XSS 1.Phishing with XSS 跨站脚本攻击,在表单中输入超文本代码 在网页中形成一个自制的登陆表单,然后将结果反馈到自己的主机上. 攻击成功 2.Store ...

  3. 20155220 Exp2 后门原理与实践

    20155220 Exp2 后门原理与实践 1.Windows获得Linux Shell 在windows下,打开CMD,使用ipconfig指令查看本机IP 然后使用ncat.exe程序,ncat. ...

  4. 20155238 2016-2017-2 《JAVA程序设计》第八周学习总结

    教材学习内容总结 第十四章 NIO NIO使用频道(Channel)来衔接数据节点,处理数据时,NIO可以让你设定缓冲区(Buffer)容量, 在缓冲区对感兴趣的数据区块进行标记,对于这些标记,提供了 ...

  5. POJ 2299

    上课讲了下数据结构,因为暂时没找到分块的板子题,所以做一下这道题加深一下对树状数组的理解. 题意就是求逆序对,从逆序对的定义就可以看出,方法有两种:归并 or 树状数组. 感觉树状数组更高级一点,写起 ...

  6. Java容器类List、ArrayList、Vector及map、HashTable、HashMap的区别与用法

    Java容器类List.ArrayList.Vector及map.HashTable.HashMap的区别与用法 ArrayList 和Vector是采用数组方式存储数据,此数组元素数大于实际存储的数 ...

  7. spring boot 实现文件下载

    html 代码 js部分 window.location.href= this.Baseurl+'/plan/down?file='+filename; spring boot 后台代码@GetMap ...

  8. Js_图片轮播

    <!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <m ...

  9. Apache Ignite 学习笔记(四): Ignite缓存冗余备份策略

    Ignite的数据网格是围绕着基于内存的分布式key/value存储能力打造的.当初技术选型的时候,决定用Ignite也是因为虽然同样是key/value存储,它有着和其他key/value存储系统不 ...

  10. 团队作业week9

    1. Bug bash ▪ How many bugs is found in your bug bash? 2. Write a blog to talk about your scenario t ...