ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

模拟72 考试总结

2021-10-09 18:32:57  阅读:123  来源: 互联网

标签:ch int 模拟 最大值 72 ull inline 考试 mp


考试经过

开场T1发现状压dp,写了2h和暴力拍上了,觉得比较稳
T2直接模拟的,T3开始以为二分后来假了,于是暴力匹配+玄学记忆化+剪枝,不知道有多少分
T4很不可做的样子,于是暴力+测试点分治走人了
然而T1挂了,20+47+100+20=187,直接转移给最大值是不对的,样例太水了。。

T1 出了个大阴间题

分析一下假如这一位上可以取1,2,3,4,5,然而下一位一定会转移到1e5,这种情况下1,2,3,4,5都可以有贡献,然而你只记了答案为5的方案数,显然没有算够,所以只转移给最大值是错误的
正确做法是多开一维记录最大值,发现最大值只有\(2n\)种,所以可以map记忆化,\(f\)数组代表当前最大值的方案数,\(g\)代表当前最大值的价值和,有了这个就有正确性了,转移复杂度\(2^n\times n^2\)
对于\(b\)由于都是一堆和一个合并,所以取值也很有限,固定的已合并数的\(b\)是相同的

#include <bits/stdc++.h>
using namespace std;
#define int long long
const int mod=1e9+7;
int f[1<<19][40],g[1<<19][40],a[20],n,k;
vector <int> sta[20];
inline int getsum(int x)
{
	int s=0;
	while(x)
	{
		if(x&1)s++;
		x>>=1;
	}
	return s;
}
unordered_map <int,int> mp;
int tot,rk[40];
inline void ins(int x)
{	
	if(mp.find(x)==mp.end())mp[x]=++tot,rk[tot]=x;
}
int v[25]={0,0,1,3,7,15,31,63,127,255,511,1023,2047,4095,8191,16383,32767,65535,131071,262143,524287};
signed main()
{
	freopen("repair.in","r", stdin);
	freopen("repair.out","w",stdout);
	cin>>n>>k;
	for(int i=1;i<=n;i++)scanf("%lld",&a[i]);
	for(int i=1;i<=n;i++)ins(a[i]),ins(a[i]+1);
	for(int i=1;i<(1<<n);i++)sta[getsum(i)].push_back(i);
	for(int i=1;i<=n;i++)f[1<<(i-1)][mp[a[i]]]=1;
	for(int i=1;i<n;i++)
	{
		for(int j=0;j<sta[i].size();j++)
		{
			int s=sta[i][j];
			for(int p=1;p<=tot;p++)
			{
				int w=rk[p];if(!f[s][p])continue;
				for(int l=1;l<=n;l++)
				{
					if((s>>(l-1))&1)continue;
					int ww=a[l],ga=mp[a[l]];
					if(w<ww)
					{
						f[s|(1<<(l-1))][ga]=(f[s|(1<<(l-1))][ga]+f[s][p])%mod;
						g[s|(1<<(l-1))][ga]=(g[s|(1<<(l-1))][ga]+g[s][p]+f[s][p]*(k*ww%mod+v[i])%mod)%mod;
					}
					if(w==ww)
					{
						int tt=mp[w+1];
						f[s|(1<<(l-1))][tt]=(f[s|(1<<(l-1))][tt]+f[s][p])%mod;
						g[s|(1<<(l-1))][tt]=(g[s|(1<<(l-1))][tt]+g[s][p]+f[s][p]*(k*(ww+1)%mod+v[i])%mod)%mod;
					}
					if(w>ww)
					{
						f[s|(1<<(l-1))][p]=(f[s|(1<<(l-1))][p]+f[s][p])%mod;
						g[s|(1<<(l-1))][p]=(g[s|(1<<(l-1))][p]+g[s][p]+f[s][p]*(k*w%mod+v[i])%mod)%mod
					}
				}	
			}
		}		
	}
	for(int i=tot;i>=1;i--)
	{
		if(f[(1<<n)-1][i])
		{	
			cout<<rk[i]<<" "<<g[(1<<n)-1][i]<<endl;
			return 0;
		}
	}
	return 0;
}

T2 最简单辣快来做

T3 是我的你不要抢

image
所以这个题解实际证明了暴力复杂度是对的?
记忆化一下,貌似不需要什么特殊处理
正解似乎是AC自动机上的数据结构,但复杂度差不多

#include <bits/stdc++.h>
using namespace std;
#define ull unsigned long long
inline int read()
{
	int x=0;char ch=getchar();
	while(ch<'0'||ch>'9')ch=getchar();
	while(ch>='0'&&ch<='9')x=(x<<1)+(x<<3)+(ch^48),ch=getchar();
	return x;
}
const int N=600060;
char a[N];vector <ull> ha[N];
ull p[N];int n,q,l[N];
inline ull get(int i,int l,int r)
{
	return ha[i][r]-ha[i][l-1]*p[r-l+1];
}
unordered_map <ull,int> mp;
inline ull ganhash(int x,int y)
{
	return (ull)x*5e6+y;
}
signed main()
{
	freopen("string.in","r",stdin);
	freopen("string.out","w",stdout);
	cin>>n>>q;
	p[0]=1;for(int i=1;i<=6e5;i++)p[i]=p[i-1]*131;
	for(int i=1;i<=n;i++)
	{
		scanf("%s",a+1);l[i]=strlen(a+1);
		ull h=0;ha[i].push_back(h);
		for(int j=1;j<=l[i];j++)
		{
			h=h*131+(a[j]-'a'+1);
			ha[i].push_back(h);	
		}
	}
	for(int i=1;i<=q;i++)
	{
		int x=read(),y=read();ull hh=ganhash(x,y);
		if(mp.find(hh)!=mp.end())
		{printf("%d\n",mp[hh]);continue;}
		int ma=0,lim=min(l[x],l[y]);
		for(int j=lim;j>=1;j--)
		{
			if(get(x,l[x]-j+1,l[x])==get(y,1,j))
			 {ma=j;break;}
		}
		mp.insert(make_pair(hh,ma));
		printf("%d\n",ma);
	}
	return 0;
}

T4 显然也是我整的

考试总结

知道的就是对拍数据一定要强一点
还有速度应该上去一些

标签:ch,int,模拟,最大值,72,ull,inline,考试,mp
来源: https://www.cnblogs.com/PMZG/p/15387143.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有