多校A层冲刺NOIP2024模拟赛04

A. 02表示法

对要求的数二进制拆分,每一位递归求解,大于2就继续拆,是1返回 \(2(0)\) ,是2返回 \(2\),由于外层的数比较大,所以

要写一个高精除低精

点击查看代码
#include<bits/stdc++.h>
#define int long long
const int maxn=1e5+10;
using namespace std;
int n,ans[maxn],top;
string s,t;

void pre(string s)
{
	s=" "+s;
	t=" "+t;
	while(s[1]-'0'>0||s.size()>1)
	{
		int len=s.size()-1,x=0,cnt=0,i;
		for(i=1;i<=len&&s[i]=='0';i++); 
		for(;i<=len;i++)
		{
			x=x*10+s[i]-'0';
			int z=x/2;
			t=t+(char)(z+'0');
			x=x-(t[++cnt]-'0')*2;
		}
//		cout<<s<<endl; 
		s=t;t=" "; 
		ans[++top]=x;	 
	}
}
void lsx(int x)
{
	if(x>1)
	{
		int cnt=0;
		for(int i=62;i>=0;i--) if((1ll<<i)&x) cnt++;
		cout<<2<<"(";
		for(int i=62;i>=0;i--)
		{
			if((1ll<<i)&x)
			{
				lsx(i);
				if(--cnt) cout<<"+";
				
			}			
		}
		cout<<")";
	}
	else
	{
		if(x==1)cout<<2;
		else cout<<"2(0)";
		return ;
	}
}

signed main()
{
	freopen("pow.in","r",stdin);
	freopen("pow.out","w",stdout);
	ios::sync_with_stdio(0);
	cin.tie(0),cout.tie(0);
	cin>>s;
	pre(s);
	int i,temp,sum=0; 
	for(i=top;i>=1&&ans[i]==0;i--);temp=i;
	for(i=temp;i>=1;i--) if(ans[i]==1)sum++;
	for(i=temp;i>=1;i--)
	{
		if(ans[i]==1)
		{
			lsx(i-1);
			if(--sum) cout<<"+";
		}			
	}

	return 0;
}
/*
261770307610118667978710393358
*/

B. 子串的子串

由于子串中有重复的,我们假设有两个相邻的重复字串 \(s1(l1,r1),s2(l2,r2)\),所以我们枚举长度,再枚举左端点,对每一个

相邻的重复子串的 \(l1-r2\) 减一,再用二维前缀和求出每个区间的答案,这样就相当于对于每一对相邻的重复子串,把靠后的那

个删掉,只保留第一个,这样不管后面是否有重复字串,加进来一个影响就消掉一个。

点击查看代码
#include<bits/stdc++.h>
#define int unsigned long long
const int base=133; 
const int maxn=3010;
using namespace std;
int n,q,ha[maxn],po[maxn],ans[maxn][maxn];
string s;
unordered_map<int,int>mp;
int jie(int l,int r)
{
	return ha[r]-ha[l-1]*po[r-l+1];
}

signed main()
{
	freopen("substring.in","r",stdin);
	freopen("substring.out","w",stdout);
	ios::sync_with_stdio(0);
	cin.tie(0),cout.tie(0);
	cin>>n>>q;
	cin>>s;s=" "+s;
	po[0]=1;
	for(int i=1;i<=n;i++)ha[i]=ha[i-1]*base+s[i],po[i]=po[i-1]*base;
	for(int len=1;len<=n;len++)
	{
		mp.clear(); 
		for(int l=1;l+len-1<=n;l++)
		{
			int r=l+len-1;
			int tem=jie(l,r);
			ans[mp[tem]][r]--;
			mp[tem]=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 x,y;
		cin>>x>>y;
		cout<<ans[x][y]<<'\n';
	}

	return 0;
}
/*

*/

C. 魔法咒语

题解说的听明白的,直接粘了
image

点击查看代码
#include<bits/stdc++.h>
#define int long long
const int maxn=2e5+10;
using namespace std;
int n,ans;
string s[maxn];
bool flag[26],vis[26];

struct lsx
{
	int tr[maxn][26],cnt[maxn],n;
	lsx():n(0){}
	void insert(string s,bool k)
	{
		int p=0;
		if(k)
		{
			for(int i=0;i<s.size();i++)
			{
				int t=s[i]-'a';
				if(!tr[p][t]) tr[p][t]=++n;
				p=tr[p][t];
			}
		}
		else
		{
			for(int i=s.size()-1;i>=0;i--)
			{
				int t=s[i]-'a';
				if(!tr[p][t]) tr[p][t]=++n,cnt[t]++;
				p=tr[p][t];
			}
		}
	}
}t1,t2;

signed main()
{
	freopen("magic.in","r",stdin);
	freopen("magic.out","w",stdout);
	ios::sync_with_stdio(0);
	cin.tie(0),cout.tie(0);
	cin>>n;
	for(int i=1;i<=n;i++)
	{
		cin>>s[i];
		t1.insert(s[i],1);
		t2.insert(s[i],0);
		flag[s[i][s[i].size()-1]-'a']=1;
		if(s[i].size()==1&&!vis[s[i][0]-'a']){ans++,vis[s[i][0]-'a']=1;}
	}
//	return 0;
	for(int i=1;i<=t1.n;i++)
	{
		for(int j=0;j<=25;j++)
		{
			if(!t1.tr[i][j])
			{
				ans+=t2.cnt[j];
//				cout<<i<<" "<<j<<endl;
			}
			else if(flag[j])ans++;
		}
	}
	cout<<ans<<'\n';

	return 0;
}
/*

*/

stars

image

posted @ 2024-10-10 08:23  _君の名は  阅读(8)  评论(0编辑  收藏  举报