首页 > 其他分享 >题解:SP15553 STC00 - Hamsters

题解:SP15553 STC00 - Hamsters

时间:2024-10-02 17:45:42浏览次数:6  
标签:STC00 int 题解 ll Hamsters len hashh 名字 mod

首先,通过预处理计算每个名字的哈希值,然后利用哈希检查名字之间的最长公共前缀,从而确定从一个名字转移到另一个名字的最小代价。

使用倍增动态规划计算转移的最小成本,\(f_{t,i,j}\) 表示从名字 \(i\) 经过 \(2^t\) 步转移到名字 \(j\) 的最小代价,最后通过位运算处理 \(M\) 次转移的组合,最终得到答案。

代码:

#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int N=210,L=100010,mod=19260817;
char s[N][L];
ll f[35][N][N],dis[N],tmp[N],n,m,ans;
int len[N],hashh[N][L],pow_26[L];
bool check(int x,int y,int l) {
	return (ll)(hashh[x][len[x]-1]-hashh[x][len[x]-l-1]+mod)%mod==(ll)((ll)hashh[y][l-1]*pow_26[len[x]-l]%mod);
}
void init() {
	pow_26[0]=1;
	for(int i=1; i<=100000; i++)
		pow_26[i]=pow_26[i-1]*26%mod;
	memset(f,0x3f,sizeof(f));
}
int main() {
	init();
	scanf("%lld%lld",&n,&m);
	m--;
	for(int i=1; i<=n; i++) {
		scanf("%s",s[i]);
		len[i]=strlen(s[i]);
		dis[i]=len[i];
		for(int j=0; j<len[i]; j++)
			if(j) hashh[i][j]=(hashh[i][j-1]+pow_26[j]*(s[i][j]-'a'+1))%mod;
			else hashh[i][j]=s[i][j]-'a'+1;
	}
	for(int i=1; i<=n; i++)
		for(int j=1; j<=n; j++) {
			int l=min(len[i],len[j]);
			for(int k(i==j?l-1:l); k; --k)
				if(check(i,j,k)) {
					f[0][i][j]=len[j]-k;
					break;
				}
			if(f[0][i][j]>10000000) f[0][i][j]=len[j];
		}
	for(int t=1; t<=30; t++)
		for(int k=1; k<=n; k++)
			for(int j=1; j<=n; j++)
				for(int i=1; i<=n; i++)
					f[t][i][j]=min(f[t-1][i][k]+f[t-1][k][j],f[t][i][j]);
	for(int i=0;i<=30;i++)
		if(m&(1<<i)) {
			for(int j=1; j<=n; j++) {
				tmp[j]=0x3f3f3f3f3f3f3f3fll;
				for(int k=1; k<=n; k++)
					tmp[j]=tmp[j]<dis[k]+f[i][k][j]?tmp[j]:dis[k]+f[i][k][j];
			}
			for(int j=1; j<=n; j++)
				dis[j]=tmp[j];
		}
	ans=0x3f3f3f3f3f3f3f3fll;
	for(int i=1; i<=n; i++)
		ans=min(ans,dis[i]);
	printf("%lld\n",ans);
	return 0;
}

标签:STC00,int,题解,ll,Hamsters,len,hashh,名字,mod
From: https://www.cnblogs.com/cly312/p/18444922

相关文章

  • 题解:AT_abc373_d [ABC373D] Hidden Weights
    可以发现一个性质:对于图的每个连通分量,一旦在其中任何顶点上的值固定,则所有写入的值都是确定的。我们可以逐个DFS每个连通分量,按照题目的要求给每个点赋值,初始搜索的点值设成\(0\)即可。代码:#include<bits/stdc++.h>#defineintlonglongusingnamespacestd;intn,m;......
  • 题解:SP19382 STK - Stock
    一道动态规划题。先分析状态。\(dp_{i\operatorname{and}1,k}\):表示在第\(i\)天最多进行\(k\)次交易的最大利润。\(s_{i\operatorname{and}1,k}\):表示在第\(i\)天之前的某天卖出之后,最多进行\(k-1\)次交易的最大利润减去当天的价格。接下来分析转移方程当\(i=0\)......
  • 题解:SP23875 DCEPC14A - Another Version of Inversion
    我们注意到这道题是二维的,所以要用到二维树状数组,不会的可以看一下这篇文章。这题的思路和P1908很像,按价值从大到小排序,排完序之后用树状数组维护,每次把这个数的位置加入到树状数组中,因为是排完序之后,所以之前加入的一定比后加入的大,然后在查询当前这个数前面位置的数(是前面位......
  • 题解:SP20038 SNGLOOP1 - Easiest Loop 1
    数学题。根据题目中给出的等式:\[(2n+3)(p-1)+\frac{4}{5}[(p\cdot{S}_{n})-{S}_{m}]=2(m-n)\]变形:\[(10n+15)(p-1)+4[(p\cdot{S}_{n})-{S}_{m}]=10m-10n\]\[(10m+15)p-10m-15+4{S}_{n}p-4{S}_{m}=10m-10n\]\[(10m+15+4{S}_{n})p=10m+15+4{S}_{m}\]\[p=\frac{10m+15+4{S}......
  • 题解:P1701 [USACO19OPEN] Cow Evolution B
    这题的关键就在于能否将问题转化成集合之间是否有交集。首先,考虑一个我们无法形成进化树的例子,例如这样:31fly1man2flyman如果我们想根据这个输入构建一棵树,我们需要在根上分割A或B,但剩下的两个子树都需要有一条边来添加另一个特征。显然输出为"No"。如果我们输入......
  • 题解:SP4555 ANARC08F - Einbahnstrasse
    一道多源最短路问题,肯定用Floyd,还有个问题就是怎么处理输入。使用sscanf(edge+2,"%d",&cost);从edge的第三个字符开始读取边权,然后处理左右两侧的箭头即可。#include<bits/stdc++.h>usingnamespacestd;map<string,int>cn;intct;intq[1028];intadd_city(constch......
  • 题解2:SP5449 ANARC09A - Seinfeld
    思路:考虑贪心。统计未配对的{:当遇到一个{时,增加未配对的{数量。当遇到一个}时,有两种情况:如果有多余的{,那么就用这个}与之前的{配对。如果没有多余的{,增加\(1\)次。遍历结束后:当我们遍历完字符串后,可能还会剩下一些未配对的{,需要通过将一部分{......
  • 题解:SP5449 ANARC09A - Seinfeld
    可以用动态规划解决。动态规划思想:设\(dp_{i,j}\)表示处理到字符串的第\(i\)个字符,并且未配对的{数量为\(j\)时,所需的最小操作次数。状态转移:初始化:\(dp_{0,0}=0\):表示空字符串且没有未配对的{,显然不需要任何操作。其他所有\(dp_{0,j}\)初始化为INF,表示不......
  • 题解:SP1703 ACMAKER - ACM (ACronymMaker)
    题目大意:一个有一些单词组成的短语,给定一个缩写词,求此缩写由此短语的单词组成的可能方案数。注意,短语中所有重要的单词都要用到,顺序必须和缩写词单词顺序一致。思路动态规划设置:\(dp_{i,j}\):使用前\(i\)个重要单词形成前\(j\)个缩写字符的方法数。\(dp2_{k,m}\):辅助数组......
  • 题解:SP4557 ANARC08H - Musical Chairs
    约瑟夫问题,由于问题涉及大量的删除和查找操作,直接用数组模拟会超时,可以用树状数组题意在每一轮游戏中,我们需要从当前的孩子位置开始数数,并淘汰第\(D\)个孩子。游戏需要不断地从剩下的孩子中进行选择并淘汰,直到只剩下最后一个孩子。注意两个点将树状数组的位置设为\(1\)......