多校A层冲刺NOIP2024模拟赛04

02表示法

直接递归即可,稍微写个高精。

点击查看代码
#include<bits/stdc++.h>
using namespace std;

//#define int __int128
const int N=1e4;
string s;
int b[N],c[N],len;
int a[N],tot;

int read()
{
	int f=1,s=0;char ch=getchar();
	while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
	while(ch>='0'&&ch<='9'){s=(s<<1)+(s<<3)+(ch^48);ch=getchar();}
	return f*s;
}

void dfs(int x,int m)
{
	if(x<=1)
	{
		if(x==0) printf("2(0)");
		if(x==1) printf("2");
		return ;
	} 
	int pos=m;
	int d=1;
	for(int i=1;i<=m;i++)
	{
		if(x&(d<<(i-1)))
		{
			pos=i;
			break;
		}
	}
	for(int i=m;i>=1;i--)
	{
		if(!(x&(d<<(i-1)))) continue;
		if(i>2) 
		{
			printf("2(");
		}
		int y=i,tot=0;
		while(y) tot++,y=y>>1;
		dfs(i-1,tot);
		if(i>2)
		{
			printf(")");
		}
		if(i>pos) printf("+");	
	}
	return ;
}


void chu()
{
	for(int i=0;i<len;i++)
	{
		if(b[i]%2==0) b[i]/=2;
		else b[i]/=2,b[i+1]=b[i+1]+10; 
	}
	int tmp=len,cnt=0;
	int flag=1;
	for(int i=0;i<len;i++)
	{
		if(b[i]==0&&flag) 
		{
			tmp--;
			continue;
		}
		if(b[i]!=0) flag=0;
		c[++cnt]=b[i];
	}
	len=tmp;
	cnt=0;
	for(int i=0;i<len;i++) b[i]=c[++cnt];
}

signed main()
{
	freopen("pow.in","r",stdin);
	freopen("pow.out","w",stdout);
	cin>>s;
	len=s.size();
	for(int i=0;i<len;i++) b[i]=s[i]-'0';
	
	while(len!=0)
	{
		a[++tot]=(b[len-1]&1);
		chu();
	}
	int pos=tot;
	for(int i=1;i<=tot;i++)
	{
		if(a[i]==1)
		{
			pos=i;
			break;
		}
	}
	for(int i=tot;i>=1;i--)
	{
		if(a[i]==0) continue;
		if(i>2) 
		{
			printf("2(");
		}
		int y=i,tot=0;
		while(y) tot++,y=y>>1;
		dfs(i-1,tot);
		if(i>2)
		{
			printf(")");
		}
		if(i>pos) printf("+");
	}
}

子串的子串

考虑二维前缀和直接容斥,再用 \(hash\) 优化一下复杂度。

点击查看代码
#include<bits/stdc++.h>
using namespace std;

#define int unsigned long long
const int N=4e3+107;
int n,q;
int ans[N][N];
string s;
unordered_map<int,int>mp;
int cnt=0;

const int base=137;
int p[N],has[N];
int get_hash(int l,int r)
{
	return has[r]-has[l-1]*p[r-l+1];
}

int read()
{
	int f=1,s=0;char ch=getchar();
	while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
	while(ch>='0'&&ch<='9'){s=(s<<1)+(s<<3)+(ch^48);ch=getchar();}
	return f*s;
}

signed main()
{
	freopen("substring.in","r",stdin);
	freopen("substring.out","w",stdout);
	n=read(),q=read();
	cin>>s;s=' '+s;
	p[0]=1;
	for(int i=1;i<=n;i++) p[i]=p[i-1]*base;
	for(int i=1;i<=n;i++) has[i]=has[i-1]*base+s[i];
	for(int len=1;len<=n;len++)
	{
		mp.clear();
		for(int l=1;l+len-1<=n;l++)
		{
			int r=l+len-1;
			int tmp=get_hash(l,r);
			ans[mp[tmp]][r]--;
			mp[tmp]=l;
		}
	}
	for(int l=n;l>=1;l--)
		for(int r=l;r<=n;r++)
			ans[l][r]+=ans[l+1][r]+ans[l][r-1]-ans[l+1][r-1]+1;

	for(int i=1;i<=q;i++)
	{
		int l=read(),r=read();
		printf("%lld\n",ans[l][r]);
	}
}

魔法咒语

正反分别建一颗trie树。直接看题解吧,挺详细的。

点击查看代码
#include<bits/stdc++.h>
using namespace std;

#define int long long
const int N=3e5+107;
const int base=137;
string s[N];
int n,len[N];
bool flag[N],vis[N];
struct lmy
{
	int n,tr[N][26];
	int cnt[26];
	void insert(string s,bool vis)
	{
		int rt=0,len=s.length();
		if(!vis)
		{
			for(int i=0;i<len;i++)
			{
				int ch=s[i]-'a';
				if(!tr[rt][ch]) tr[rt][ch]=++n;
				rt=tr[rt][ch];
			}
		}
		else
		{
			for(int i=len-1;i>=0;i--)
			{
				int ch=s[i]-'a';
				if(!tr[rt][ch]) tr[rt][ch]=++n,++cnt[ch];
				rt=tr[rt][ch];
			}
		}
	}
}tr1,tr2;

int read()
{
	int f=1,s=0;char ch=getchar();
	while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
	while(ch>='0'&&ch<='9'){s=(s<<1)+(s<<3)+(ch^48);ch=getchar();}
	return f*s;
}

signed main()
{
	freopen("magic.in","r",stdin);
	freopen("magic.out","w",stdout);
	n=read();
	tr1.n=tr2.n=0;
	int ans=0;
	for(int i=1;i<=n;i++)
	{
		cin>>s[i];
		tr1.insert(s[i],0);
		tr2.insert(s[i],1);
		int len=s[i].length();
		vis[s[i][len-1]-'a']=1;
		if(len==1&&!flag[s[i][0]-'a']) ans++,flag[s[i][0]-'a']=1;
	}
	for(int i=1;i<=tr1.n;i++)
	{
		for(int x=0;x<26;x++)
		{
			if(!tr1.tr[i][x]) ans+=tr2.cnt[x];
			else if(vis[x]) ans++;
		}
	}
	printf("%lld\n",ans);
}
posted @ 2024-10-12 21:18  zhengchenxi  阅读(13)  评论(0编辑  收藏  举报