首页 > 其他分享 >[SDOI2009] Bill的挑战

[SDOI2009] Bill的挑战

时间:2023-07-17 21:47:17浏览次数:35  
标签:状态 le 位置 挑战 Bill ms 字符串 SDOI2009 aligned

[SDOI2009] Bill的挑战

目录

题目描述

Sheng_bill 不仅有惊人的心算能力,还可以轻松地完成各种统计。在昨天的比赛中,你凭借优秀的程序与他打成了平局,这导致 Sheng_bill 极度的不满。于是他再次挑战你。这次你可不能输。

这次,比赛规则是这样的:

给出 \(N\) 个长度相同的字符串(由小写英文字母和 ? 组成),\(S_1,S_2,\dots,S_N\),求与这 \(N\) 个串中的刚好 \(K\) 个串匹配的字符串 \(T\) 的个数,答案对 \(1000003\) 取模。

若字符串 \(S_x(1\le x\le N)\) 和 \(T\) 匹配,满足以下条件:

  1. \(|S_x|=|T|\)。
  2. 对于任意的 \(1\le i\le|S_x|\),满足 \(S_x[i]= \texttt{?}\) 或者 \(S_x[i]=T[i]\)。

其中 \(T\) 只包含小写英文字母。

输入格式

本题包含多组数据

第一行一个整数 \(T\),表示数据组数。

对于每组数据,第一行两个整数,\(N\) 和 \(K\)。

接下来 \(N\) 行,每行一个字符串 \(S_i\)。

输出格式

每组数据输出一行一个整数,表示答案。

样例 #1

样例输入 #1

5

3 3

???r???

???????

???????

3 4

???????

?????a?

???????

3 3

???????

?a??j??

????aa?

3 2

a??????

???????

???????

3 2

???????

???a???

????a??

样例输出 #1

914852

0

0

871234

67018

提示

数据规模与约定

  • 对于 \(30\%\) 的数据,\(N\le5\),\(|S_i|\le20\);
  • 对于 \(70\%\) 的数据,\(N\le13\),\(|S_i|\le30\);
  • 对于 \(100\%\) 的数据,\(1\le T\le 5\),\(1\le N \le15\),\(1\le|S_i|\le50\)。

题意概括

我去真不是我说,这个题我真没看懂它到底让我干啥。

后来去看\(OJ\)上的题面,才知道那个长得跟绝对值一样的符号是长度的意思…………

总之是这样的:

给你\(N\)个字符串、你可以从这些字符串里挑选\(K\)个,对这\(K\)个字符串配对出字符串\(T\),配对规则倒是比较简单:

  1. \(K\)个字符串长度和\(T\)相同。

  2. 对于\(K\)个字符串,每一位必须是'\(?\)'或者与字符串\(T\)的对应位置相同。

也就是说,如果选出的\(K\)个字符串上某一位上都是'\(?\)',那么这一位可以选择\(26\)个字母。

如果选出的\(K\)个字符串上某一位不是'\(?\)',那么这一位可以选择这一种字母。

如果选出的\(K\)个字符串某两位不是'\(?\)'且各不相同,那么这一位的选择为\(0\),整个字符串\(T\)的选择为0。

思路历程

私货:†升天††升天†。

1.设计转移

上来就设计转移!上来就设计转移!

我们就是选嘛,去选一个字符串\(T\),\(f_{i}\)表示第\(0\)~\(i\)位置有多少种方案嘛,那显然\(1<=i<=50,'a'<=j<='z'\)嘛。

那么我们的转移大抵是这样的:

\[\begin{aligned} f_{i}=max(f_{i},f_{i-1}+第i位置所有可能) \end{aligned} \]

然后我们查询最后的\(f_n\)就结束了嘛。

预处理一下第\(i\)位置的方案数就好了嘛。

2.有没有发现少了个\(K\)

刚刚的只适用于\(N==K\)。

显然只适合骗分(

最初呢,我想的是没有关系嘛,我们可以枚举每一个方案~

然而仔细一想,一方面我不会枚举,另一方面万一咱选的\(T\)里面有重的也没办法去掉。(而且这和状态压缩有半毛钱关系)

那我们肯定要更改我们的转移了。

先设计状态,这个设计的状态要满足我们的关键问题:处理\(K\).

我们每一个位置设计一个状态\(ms_{i,j}\),表示选出的字符串\(T\)的第\(i\)位置如果是字符\(j\),可以和哪些字符串配对。

例如:

ms[0][a]=3;

//第0位的字符为a,状态为0 1 1,表示可以与第一个和第二个字符串配对。

那么,对于这个\(ms\)数组的初始化是这样的:

ms初始化
/*
变量声明:
len是字符串的长度,都一样长
S存的是字符串,S[k][i]表示第k个字符串的第i位置
*/

for(int i=0;i<len;++i){
	for(char j='a';j<='z';++j){
		for(int k=1;k<=n;++k){
			if(S[k][i]=='?' || S[k][i]==j){
				ms[i][j-'a']|=(1<<(k-1));
			}
		}
	}
}

有了这个,我们选状态就可以了呀,\(f_{i,j}\)表示\(0-i\)位置第\(i\)位置的状态是\(j\)时的方案数。

就有转移:

\[\begin{aligned} f_{i+1,ms_{i,ch} 与 j}+=f_{i,j} \end{aligned} \]

为什么是加?因为我们这个\(j\)是枚举的状态,所有状态都会加进下一位与他有重叠的状态里。

因为是不断往下走状态中的\(1\)越走越少,因此显然有初始化:

\(f_{0,(1<<n)-1}=1\)

最后我们找答案肯定是从状态中\(1\)的个数等于\(K\)的里面找。

代码实现

Miku's Code
#include<bits/stdc++.h>
using namespace std;

typedef long long intx;
const int maxn=16,maxS=55,maxs=1<<15,mod=1000003;

int T,n,k,len;
char S[maxS][maxS];
int f[maxS][maxs],ms[maxS][27];

inline void input(){
	memset(f,0,sizeof(f));
	memset(ms,0,sizeof(ms));
	scanf("%d %d",&n,&k);
	for(int i=1;i<=n;++i){
		scanf("%s",S[i]);
	}
	len=strlen(S[1]);
	for(int i=0;i<len;++i){
		for(char j='a';j<='z';++j){
			for(int k=1;k<=n;++k){
				if(S[k][i]=='?' || S[k][i]==j){
					ms[i][j-'a']|=(1<<(k-1));
				}
			}
		}
	}
}

inline void work(){
	f[0][(1<<n)-1]=1;
	for(int i=0;i<len;++i){
		for(int j=0;j<=(1<<n)-1;++j){
			if(f[i][j]){
				for(char ch='a';ch<='z';++ch){
					f[i+1][ms[i][ch-'a']&j]+=f[i][j];
					f[i+1][ms[i][ch-'a']&j]%=mod;	
				}
			}
		}
	}
}

inline int lowbit(int x){
	return x&(-x); 
}

inline int count_(int s){
	int cnt=0;
	while(s){
		s=s-lowbit(s);
		++cnt;
	}
	return cnt;
}

int answer(){
	int ans=0;
	for(int i=0;i<=(1<<n)-1;++i){
		if(count_(i)==k)	ans=(ans+f[len][i])%mod;
		//因为work()中枚举的i到len-1,转移到len,所以是len 
	}
	return ans; 
}

int main(){
	scanf("%d",&T);
	for(int i=1;i<=T;++i){
		input();
		work();
		printf("%d\n",answer());
	}
	return 0;
} 

标签:状态,le,位置,挑战,Bill,ms,字符串,SDOI2009,aligned
From: https://www.cnblogs.com/sonnety-v0cali0d-kksk/p/17561324.html

相关文章

  • [极客大挑战 2019]EasySQL
    [极客大挑战2019]EasySQL题目来源:buuctf题目类型:web涉及考点:SQL注入先看题目,给了两个输入框:随便输入几个数进去,例如username=123,password=123:页面回显说是错误的用户密码,但注意到url中采用的是get传参:下一步寻找注入点,我们可以假设数据库中的查询语句为:select......
  • 青橙色调挑战电影质感
    阴影部分都是冷调的高光部分偏暖色-对比度(温馨的感觉)......
  • 挑战程序竞赛系列(74):4.3强连通分量分解(1)
    挑战程序竞赛系列(74):4.3强连通分量分解(1)传送门:POJ2186:PopularCows题意:每头牛都想成为牛群中的红人。给定N头牛的牛群和M个有序对(A,B)。(A,B)表示牛A认为牛B是红人。该关系具有传递性,所以如果A认为B是红人,B认为C是红人,则A认为C是红人。注意:给定的有序对中可能包含(A,B)和(B,C......
  • 挑战程序竞赛系列(70):4.7后缀数组(2)
    挑战程序竞赛系列(70):4.7后缀数组(2)传送门:POJ1509:GlassBeads题意:ThedescriptionofthenecklaceisastringA=a1a2…amspecifyingsizesoftheparticularbeads,wherethelastcharacteramisconsideredtoprecedecharactera1incircularfashion.Thedisjoin......
  • 共探AI大模型时代下的挑战与机遇,华为云HCDE与大模型专家面对面
    摘要:近日,华为开发者大会2023(cloud)“开发者生态创新发展圆桌会议”在东莞华为溪流背坡村成功举办。2023年7月8日,华为开发者大会2023(cloud)“开发者生态创新发展圆桌会议”在东莞华为溪流背坡村成功举办。以大模型为代表的的新一轮人工智能技术浪潮汹涌而来,在圆桌会议上,华为技术专......
  • 共探AI大模型时代下的挑战与机遇,华为云HCDE与大模型专家面对面
    摘要:近日,华为开发者大会2023(cloud)“开发者生态创新发展圆桌会议”在东莞华为溪流背坡村成功举办。2023年7月8日,华为开发者大会2023(cloud)“开发者生态创新发展圆桌会议”在东莞华为溪流背坡村成功举办。以大模型为代表的的新一轮人工智能技术浪潮汹涌而来,在圆桌会议上,华为技术专家为......
  • BZOJ 1877: [SDOI2009]晨跑 费用流拆点
    1877:[SDOI2009]晨跑TimeLimit: 4Sec  MemoryLimit: 64MBSubmit: 2271  Solved: 1215[Submit][Status][Discuss]DescriptionElaxia最近迷恋上了空手道,他为自己设定了一套健身计划,比如俯卧撑、仰卧起坐等等,不过到目前为止,他坚持下来的只有晨跑。现在给出一张......
  • 行行AI人才直播第7期:奇计AI创始人左晟《AI时代的商业挑战和机遇》
    行行AI人才是博客园和顺顺智慧共同运营的AI行业人才全生命周期服务平台,是园子商业化努力的一个重要方向。行行AI人才直播希望以直播的方式让大家更多了解AI行业的现状与未来可能的发展方向。随着人工智能技术的不断发展,我们正逐渐步入一个全新的智能时代。AI 的应用正在深......
  • 认知负担的挑战与平台工程的机遇
    开发人员与DevOps不断增加的认知负担被认为是软件工程中最大的问题之一。随着越来越多的工具、框架和方法可以选择,以及“Youbuildit,yourunit”的DevOps思想的发展,我们可以看到为了提供面向客户的产品和服务,认知负担也随之大幅增加。 在今天的文章中,我们将初步了解认......
  • 利用身份验证和授权机制,例如OAuth、JWT 和 API 密钥,APIaaS 如何帮助解决安全挑战?
    什么是APIaaS?APIaaS,即API即服务(APIasaService)是一种创新的基于云的方法,提供API(应用程序编程接口),使第三方服务提供商能够访问特定服务、数据或资源。它通过抽象内部API的复杂性,简化了开发、部署和管理API的过程。其主要目标是使开发人员和企业更容易地在其应用程序或软......