首页 > 其他分享 >ECfinal2021部分题解

ECfinal2021部分题解

时间:2022-08-22 23:55:51浏览次数:109  
标签:字符 return int 题解 30 ECfinal2021 const 部分 MOD

把赛中没有过的题争取补一下
题目链接:https://codeforces.com/gym/103861

C:
其实,最后每一种字符只有两种状态:
1.出现了x,此时就已经知道该字符有多少个了
2.没有出现x,那么相当于知道了这个字符至少有多少个记为\(L_I\)
同时,我们可以维护出每一个位置不可以填某个字符
考虑从左往右填,记录一个状态为填了前i个字符
由于有下界的限制,因此还需要每种字符已经出现了多少次
由于\(\sum L_i\le k\),因此可以简单地压成一个二进制数
至于具体出现了多少次的字符,只需要保证再出现够\(L_i\)个字符后不再转移即可
目前的写法是O(\(262^kk\))的

点击查看代码
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int MOD=1e9+7;
const int N=10005;
const int K=20;
int add (int x,int y){x=x+y;return x>=MOD?x-MOD:x;}
int mul (int x,int y){return (LL)x*y%MOD;}
int dec (int x,int y){x=x-y;return x<0?x+MOD:x;}
int Pow (int x,int y)
{
	int t=1;
	while (y)
	{
		if (y&1) t=mul(t,x);
		y>>=1;x=mul(x,x);
	}
	return t;
}
int L[30],R[30];
char s[K],t[K];
int n,m;
int cnt[30];
bool ban[K][30];
bool p[N];
void Init()
{
	scanf("%s%s",s,t);
	for (int u=0;u<26;u++) cnt[u]=0;
	for (int u=0;u<m;u++) if (t[u]=='O')
	{
		int x=s[u]-'A';
		cnt[x]++;
		for (int i=0;i<26;i++) if (i!=x) 	ban[u][i]=1;
	}
	for (int u=0;u<m;u++) if (t[u]!='O')
	{
		int x=s[u]-'A';
		ban[u][x]=1;
		if (t[u]=='-') cnt[x]++;
		else 		   {p[x]=false;R[x]=min(R[x],cnt[x]);}
	}
	for (int u=0;u<26;u++) L[u]=max(L[u],cnt[u]);
}
int mask[30];
int bel[30];
int f[K][1<<K];
int inv[30];
int main()
{
	inv[0]=1;for (int u=1;u<=20;u++) inv[u]=mul(inv[u-1],Pow(u,MOD-2));
	memset(ban,false,sizeof(ban));
	for (int u=0;u<26;u++) p[u]=true;
	scanf("%d%d",&n,&m);
	for (int u=0;u<26;u++) {L[u]=0;R[u]=m;}
	while (n--) Init();	
	
	for (int u=0;u<26;u++) if (L[u]>R[u]) {printf("0\n");return 0;}
	n=0;
	for (int u=0;u<26;u++)
	{
		mask[u]=0;
		for (int i=0;i<L[u];i++)
		{
			mask[u]|=(1<<n);bel[n]=u;n++;	
			if (n>m) {printf("0\n");return 0;}
		}
	}
	f[0][0]=1;
	for (int u=0;u<m;u++)
	for (int i=0;i<(1<<n);i++)
	{
		if (!f[u][i]) continue;
		for (int k=0;k<n;k++) if (!ban[u][bel[k]]&&!((i>>k)&1))	
		{
		
			f[u+1][i|(1<<k)]=add(f[u+1][i|(1<<k)],f[u][i]);
		}
		for (int k=0;k<26;k++) if (p[k]&&(mask[k]==(mask[k]&i))&&!ban[u][k]) 
		{
			f[u+1][i]=add(f[u+1][i],f[u][i]);
		}
	}
	int ans=f[m][(1<<n)-1];
	for (int u=0;u<26;u++) ans=mul(ans,inv[L[u]]);
	printf("%d\n",ans);
	return 0;
}

标签:字符,return,int,题解,30,ECfinal2021,const,部分,MOD
From: https://www.cnblogs.com/Als123/p/16614701.html

相关文章

  • mysql部分--安装mysql 8.0以上版本
    安装mysqlmysql本质上是一个软件一、mysql安装1.下载链接:https://downloads.mysql.com/archives/community/2.先安装windows补丁[百度网盘下载](链接:https://pan.baid......
  • 题解 CF1712D Empty Graph
    CF1712D洛谷的CF的提交无了,所以可能没人来看了,但是在题解区是清一色的二分,而唯一一篇贪心题解的讨论还略显复杂的情况下,我还是希望提供一种比较简洁的贪心题解。在复杂......
  • P5753 瓷片项链 题解
    题目分析很容易发现只要烧制所有瓷片的损耗小于总量,就能烧制成项链。不妨设烧制了\(n\)片,则总长度为\(n\times0.3\sqrt{v-v0}\)。本题数据范围较小,\(n\)的大......
  • AMD PetaLinux 2022.1中部分语法改变,不支持IMAGE_CLASSES_remove、IMAGE_FSTYPES_DEBU
    付汉杰[email protected]最新的AMDPetaLinux2022.1,不支持IMAGE_CLASSES_remove、IMAGE_FSTYPES_DEBUGFS_remove、PREMIRRORS_prepend。如果有上述关键词,会报告类似下面的错......
  • CF1715C Monoblock 题解
    思路根据题意我们不难看出,求一个区间的块的数量即求区间内\(a_i\neqa_{i-1}\)的数量,如果直接枚举每个区间的话,时间复杂度是\(\mathcalO(n^2)\)显然这样做是不行的,但......
  • CF1715B Beautiful Array 题解
    思路根据题意,不难看出,当\(b>\dfrac{s}{k}\)时,一定无解,因为无论怎样分配\(s\),最终的结果一定不会比\(\dfrac{s}{k}\)更大。然后再来考虑当\(b\le\dfrac{s}{k}\)时,......
  • CF1715A Crossmarket 题解
    思路根据题意以及下面给的样例解释,我们不难看出最优解一定是下面两种情况的一种:即一个人直接抵达目标点的距离加上另一个人走行和列,即\(n\)和\(m\)中较小的一个,加......
  • CF1715D 2+ doors 题解
    个人认为这道D比C要简单。思路因为题目中每个条件限制为$a_i\mida_j=x$,并且题目中还提到\(x<2^{30}\),我们考虑将\(x\)转换成二进制的方式表示,枚举\(x\)的......
  • 蔚来杯2022牛客暑期多校训练营加赛 题解
    E.Everyoneisbot对于后\(p\)个人,这\(p\)个人相互制约,一旦有一个人进行复读,剩下的\(p-1\)个人一定会进行复读,那么这个人就会被禁言,对于他来说不是最优策略。此时......
  • 题解 - CF1715
    C.Monoblock先考虑算出修改前的答案。这明显可以增量法\(O(n)\)。修改的时候先考虑把这里断开,然后再考虑和左右两边连上(大概三种情况,随便讨论)D.2+doors完了,口胡假了......