首页 > 其他分享 >COCI19-20#6 Trener题解

COCI19-20#6 Trener题解

时间:2024-11-14 15:40:20浏览次数:1  
标签:COCI19 Hash int 题解 long Trener dt strlen define

COCI19-20#6 Trener

link

一道水题(我真是太弱了啊啊啊啊。

众所周知,看到这个题立刻知道他是要选名字长度为 $1$ 到 $N$ 的,而我们知道他每一个名字,所以可以直接用字符哈希去做,因为他每一个名字的字符数是上一层名字的字符数加一,所以对于哈希每个字符串只需要跑三次,分别是自己的这个序列的哈希,以及去头,去尾的两个哈希值,目的是为了与上一个字符比较。

然后我想的是用加法原理一层层去跑出答案(其实和图论的思想差不多)。

易看出时间复杂度为三次方级别的,在两秒的时限下可以过掉此题。

然后模拟赛时我全部 $MLE$ 到飞起。

$50$ 昏

#include<bits/stdc++.h>
#define int long long

#define pb push_back

#define P 1145141

#define ULL unsigned long long


using namespace std;

const int N=51,K=2000,mod=1e9+7;

int n,k;
vector<int> G[N][K];
int sum;
int ans[N][K];

ULL dt[N][K][3];
ULL Hash(char s[],int i,int len)
{
	ULL res=0;
	for(;i<len;i++)
		res=res*P+s[i]-'a'+1;
	return res;
}

signed main()
{
	freopen("trener.in","r",stdin);
	freopen("trener.out","w",stdout);
	
	char a[K];
	cin>>n>>k;
	for(int i=1;i<=k;i++)
	{
		cin>>a;
		dt[1][i][2]=Hash(a,0,strlen(a));
	}
	for(int i=2;i<=n;i++)
	{
		for(int j=1;j<=k;j++)
		{
			cin>>a;
			dt[i][j][0]=Hash(a,0,strlen(a)-1);
			dt[i][j][1]=Hash(a,1,strlen(a));
			dt[i][j][2]=Hash(a,0,strlen(a));
			for(int t=1;t<=k;t++)
			{
				if(dt[i-1][t][2]==dt[i][j][0] || dt[i-1][t][2]==dt[i][j][1])
					G[i][j].pb(t);
			}
		}
	}
	
	for(int i=1;i<=k;i++)	ans[1][i]=1;
	for(int i=2;i<=n;i++)
		for(int j=1;j<=k;j++)
			for(auto t:G[i][j])	
				ans[i][j]+=ans[i-1][t],ans[i][j]%=mod;
				
	for(int i=1;i<=k;i++)	sum+=ans[n][i],sum%=mod;
	
	cout<<sum<<endl;
	return 0;
}

赛后 $5$ 分钟,我发现了我存图的动态数组的空间复杂度也是三次方级别的,直接炸掉。

然后我才看见我原来是可以把这个问题做成一个几乎在线的做法,就是把我向上递推的过程与输入合并在一起,这样就可以使我的数组减少一维。

代码

#include<bits/stdc++.h>
#define int long long

#define pb push_back

#define P 1145141

#define ULL unsigned long long


using namespace std;

const int N=51,K=1600,mod=1e9+7;

int n,k;
int sum;
int ans[N][K];
vector<int> G[K];
ULL dt[N][K][3];
ULL Hash(char s[],int i,int len)
{
	ULL res=0;
	for(;i<len;i++)
		res=res*P+s[i]-'a'+1;
	return res;
}

signed main()
{
	freopen("trener.in","r",stdin);
	freopen("trener.out","w",stdout);
//	
	char a[K];
	cin>>n>>k;
	for(int i=1;i<=k;i++)
	{
		cin>>a;
		dt[1][i][2]=Hash(a,0,strlen(a));
	}
	
	for(int i=1;i<=k;i++)	ans[1][i]=1;
	
	for(int i=2;i<=n;i++)
	{
		for(int j=1;j<=k;j++)
		{
			cin>>a;
			dt[i][j][0]=Hash(a,0,strlen(a)-1);
			dt[i][j][1]=Hash(a,1,strlen(a));
			dt[i][j][2]=Hash(a,0,strlen(a));
			for(int t=1;t<=k;t++)
				if(dt[i-1][t][2]==dt[i][j][0] || dt[i-1][t][2]==dt[i][j][1])
					G[j].pb(t);
		}
		for(int j=1;j<=k;j++)
			for(auto t:G[j])	
				ans[i][j]+=ans[i-1][t],ans[i][j]%=mod;
		for(int j=1;j<=k;j++) G[j].clear();
	}
				
	for(int i=1;i<=k;i++)	sum+=ans[n][i],sum%=mod;
	
	cout<<sum<<endl;
	return 0;
}

标签:COCI19,Hash,int,题解,long,Trener,dt,strlen,define
From: https://www.cnblogs.com/tangml/p/18546183

相关文章

  • 【题解】洛谷P11186: 三目运算
    不好玩!!!这是个树形结构,直接暴力模拟,但过不去,但是需要发现答案是个区间,我们对字符串处理时记录最大值最小值,然后到叶子节点时我们将此时的区间存起来,查询时直接二分查询这个数对于的区间就可以了。总结:不好玩!!!#include<bits/stdc++.h>usingnamespacestd;#definelllonglon......
  • 【题解】洛谷P1712: [NOI2016] 区间
    P1712[NOI2016]区间我对尺取法并不敏感,所以感觉有点难度,我们想到按照区间长度排序加入使得满足单调性,直到有一个区间的覆盖次数达到了m就可以计算了,而这个就是尺取法,单调性使得我们答案总是最优的。覆盖次数就可以用线段树做,而且数据范围很大需要离散化,计算答案时注意把答案带......
  • 题解:P11251 [GESP202409 八级] 美丽路径
    题目传送门题目大意给你一颗树,每个结点为黑色或白色。求一条路径,使得路径上距离为奇数的点颜色不同,距离为偶数的点颜色相同,输出这条路径最多能包含多少结点。思路讲解容易想到用树形动态规划搭配dfs解决。将结点1......
  • 2021年6月上海月赛T5题解(做基础123题时遇到的)
    平衡点内存限制: 256 Mb时间限制: 1000 ms题目描述给定一个由 n 个整数组成的数列a1​,a2​,⋯,an​,请为这个数列找到一个平衡点,使得平衡点左侧与右侧的力矩尽量接近。若平衡点为 ak​,则左侧力矩定义为数列中下标小于 k 的各个元素到 ak​ 的距离乘以这些元素......
  • 「AT_diverta2019_2_e」Balanced Piles 题解
    题意描述有一个长度为\(N(2\leN\le10^6)\)的数组,一开始所有元素均为\(0\)。设\(M\)为当前数组中的最大元素,\(m\)是当前数组中的最小元素,你可以执行若干次以下操作:选择一个大小为\(m\)的元素,把他变为\(x\),其中\(M\lex\leM+D\)且\(m<x\)。求有多少种操作方法......
  • [ARC105C] Camels and Bridge 题解
    [ARC105C]CamelsandBridge题解https://www.luogu.com.cn/problem/AT_arc105_c记:这是24年夏天在北京梦熊写的(模拟赛撞原),希望这年夏天fowever。sol首先\(n\)很小,所以可以去暴力枚举顺序,也就是全排列。\(W_s\)表示排列为\(s\)时的间距。又令\(f_i\)为前\(i\)只......
  • [题解]P3119 [USACO15JAN] Grass Cownoisseur G
    P3119[USACO15JAN]GrassCownoisseurG显然我们可以先跑强连通分量,由\(x\)个点缩成的新点\(u\)权值为\(v[u]=x\)。下文中的节点\(1\)均表示缩点后节点\(1\)所在的节点。我们在缩点后的DAG上跑拓扑排序,预处理出\(fa[i]\)和\(fb[i]\),分别表示“\(1\)到\(i\)路径的点权和”,“\(i......
  • 洛谷P11228的C++题解
    题目分析题目题目让我们算出机器人走步后经过了多少个不重复的点这道题不是搜索!直接按照题意模拟就行了。遇到墙就向右转,不是就直行。特别注意:向右转也是一步!一个格子最多算一遍!我们可以用一个标记数组 st,走过的点就打上标记。判断走道的点有没有打上标记,有就不......
  • P2779 [AHOI2016初中组] 黑白序列题解
    题意:小可可准备了一个未完成的黑白序列,用B和W表示黑色和白色,用?表示尚未确定。他希望知道一共有多少种不同的方法,在决定了每一个?位置的颜色后可以得到一个小雪喜欢的黑白序列。其中,小雪喜欢的黑白序列指的是对于任何正整数\(n\),由连续\(n\)个黑接上连续\(n\)个白......
  • 题解:CF2025E Card Game
    在这貌似和大部分做法不太一样(?)权当卡特兰数的复习题吧。不会卡特兰数的可以先看文末。如果没有花色\(1\)这道题就很简单了,对于每个别的花色都有\(C(m)\)种分配方案。\(C(n)\)表示卡特兰数的第\(n\)项,答案就是乘起来。发现除了花色\(1\)每种花色的牌都是独立的。这......