0224模拟赛(超!原!)

\(~~~~\) 经历了前两天答辩的洗礼现在如沐春风啊。

大梦的曲调 / 「POI2011」LIZ-Lollipop

题意

\(~~~~\) 长度为 \(n\) 的只含 \(1,2\) 的序列,\(q\) 次询问求是否存在一个区间,其和为 \(x\)。若有求出区间长度。
\(~~~~\) \(1\leq n\leq 10^6,1\leq q\leq 10^6\).

题解

\(~~~~\) 先考虑一个考场上的部分分 \(x\)\(\sum a_i\) 奇偶性相同,那么我们首先能构造 \(\sum{a_i}\) 的结果,然后要保证奇偶性相同,我们要删除两个 \(1\) 或者一个 \(2\),那么如果两边存在一个 \(2\) 就直接删 \(2\),否则两边都是 \(1\) 都得死。

\(~~~~\) 然后怎么构造不同奇偶性的?对于某个已有的 \(S\) 我们删掉 \(2\) 较少的那边即可。


方碑解密 /「ARC099F」Eating Symbols Hard

题意

\(~~~~\) 长为 \(n\) 的操作序列.初始位置为 \(0\)。四种操作分别表示将位置 \(-1\),位置 \(+1\),当前位置上数字 \(+1\),当前位置上数字 \(-1\)。求多少个子段的效果和整个序列等价。
\(~~~~\) \(1\leq n\leq 10^6\).

题解

\(~~~~\) 把每个操作过后的序列用Hash维护起来,那么我们就只需要找有多少个区间的 Hash 值和最后的一样即可。

\(~~~~\) 所以我们考虑一个区间的 Hash 值怎么求,记 \(pos\) 为那个时候的位置,那么 \(H(l,r)=Hash_{r}-Hash_{l-1}\times base^{pos}\).

\(~~~~\) 当然可能有负数那怎么办捏?当然是求逆元啦,所以要取质数模数。

\(~~~~\) 实现的时候用双Hash,不然太容易重复了。

代码
查看代码
#include <bits/stdc++.h>
#define ll long long
#define PII pair<int,int>
#define mp(a,b) make_pair(a,b)
#define ull long long
using namespace std;
template<typename T>void read(T &x)
{
    T f=1;x=0;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9') {x=x*10+ch-'0';ch=getchar();}
    x*=f;
}
int Pos[5000005];
char S[5000005];
map<pair<ull,ull>,int>buc;
const ull base1=131,P1=998244353;
const ull base2=137,P2=1e9+7;
ull Hash1[5000005],Pow1[5000005],Hash2[5000005],Pow2[5000005];
ull qpow(ull a,ull b,ull MOD)
{
	ull ret=1;
	while(b)
	{
		if(b&1) ret=ret*a%MOD;
		b>>=1;a=a*a%MOD;
	}
	return ret;
}
int main() {
//	freopen("decrypt.in","r",stdin);
//	freopen("decrypt.out","w",stdout);
	int n;read(n);
	scanf("%s",S+1);
	Pos[0]=n; Pow1[0]=Pow2[0]=1;
	for(int i=1;i<=n*2;i++) Pow1[i]=Pow1[i-1]*base1%P1,Pow2[i]=Pow2[i-1]*base2%P2;
	for(int i=1;i<=n;i++)
	{
		if(S[i]=='<') 
			Pos[i]=Pos[i-1]-1,Hash1[i]=Hash1[i-1],Hash2[i]=Hash2[i-1];
		if(S[i]=='>') 
			Pos[i]=Pos[i-1]+1,Hash1[i]=Hash1[i-1],Hash2[i]=Hash2[i-1];
		if(S[i]=='+') 
			Pos[i]=Pos[i-1],Hash1[i]=(Hash1[i-1]+Pow1[Pos[i-1]])%P1,Hash2[i]=(Hash2[i-1]+Pow2[Pos[i-1]])%P2;
		if(S[i]=='-') 
			Pos[i]=Pos[i-1],Hash1[i]=(Hash1[i-1]-Pow1[Pos[i-1]]+P1)%P1,Hash2[i]=(Hash2[i-1]-Pow2[Pos[i-1]]+P2)%P2;
	}
	pair<ull,ull> rt=mp(Hash1[n],Hash2[n]);
	ll Ans=0;
	for(int i=n;i>=1;i--)
	{
		buc[mp(Hash1[i],Hash2[i])]++;
		ull Tmp1=Pos[i-1]-n>=0?Pow1[Pos[i-1]-n]:qpow(Pow1[n-Pos[i-1]],P1-2,P1);
		ull Tmp2=Pos[i-1]-n>=0?Pow2[Pos[i-1]-n]:qpow(Pow2[n-Pos[i-1]],P2-2,P2);
		ull Val1=(Tmp1*rt.first %P1+Hash1[i-1])%P1;
		ull Val2=(Tmp2*rt.second%P2+Hash2[i-1])%P2;
		Ans+=buc[mp(Val1,Val2)];
	}
	printf("%lld",Ans);
	return 0;
}
/*
瑶草一何碧,春入武陵溪。溪上桃花无数,花上有黄鹂。我欲穿花寻路,直入白云深处,浩气展虹霓。只恐花深里,红露湿人衣。
坐玉石,欹玉枕。拂金徽。谪仙何处,无人伴我白螺杯。我为灵芝仙草,不为朱唇丹脸,长啸亦何为。醉舞下山去,明月逐人归。

把当前的碑上数字Hash表示了
那么我们就是求序列上Hash段有多少相同
只做某一段的Hash值:Hash[r]-Hash[l-1]*base^{Pos-n}
Pos表示当时的位置 

5
+>+<-
3

5
+>+-<
5
*/

遗迹谜题 / 「CF1540C2」Converging Array (Hard Version)

写不好,删了。

代码
查看代码
#include <bits/stdc++.h>
#define PII pair<int,int>
#define mp(a,b) make_pair(a,b)
using namespace std;
template<typename T>void read(T &x)
{
    T f=1;x=0;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9') {x=x*10+ch-'0';ch=getchar();}
    x*=f;
}
const int MOD=1e9+7;
inline int Add(int a,int b){a+=b;return a>=MOD?a-MOD:a;}
inline int Dec(int a,int b){a-=b;return a<0?a+MOD:a;}
inline int Mul(int a,int b){return 1ll*a*b%MOD;}
inline int qpow(int a,int b)
{
	int ret=1;
	while(b)
	{
		if(b&1) ret=Mul(ret,a);
		b>>=1;a=Mul(a,a);
	}
	return ret;
}
int n,Mem[200005];
int c[100005],b[100005];
int Pre[10005],dp[10005],Sumb[100005],Suma[100005];
int Calc(int x)
{
	if(~Mem[x+100000]) return Mem[x+100000];
	memset(Pre,0,sizeof(Pre));
	for(int i=0;i<=n*100;i++) Pre[i]=1;
	for(int i=1;i<=n;i++)
	{
		memset(dp,0,sizeof(dp));
		for(int j=0;j<=n*100;j++)
		{
			if(j<i*x+Sumb[i]) continue;
			dp[j]=Dec(Pre[j],j>c[i]?Pre[j-c[i]-1]:0);
		}
		for(int j=0;j<=n*100;j++) Pre[j]=Add(dp[j],j>0?Pre[j-1]:0);
	}
	return Mem[x+100000]=Pre[n*100];
}
template<typename T>void print(T x) {
    if(x<0) putchar('-'),x=-x;
    if(x>9) print(x/10);
    putchar(x%10+'0');
}
int main() {
//	freopen("puzzle.in","r",stdin);
//	freopen("puzzle.out","w",stdout);
	memset(Mem,-1,sizeof(Mem));
	int AnsMax=1;read(n);
	for(int i=1;i<=n;i++) read(c[i]),AnsMax=Mul(AnsMax,(c[i]+1));;
	for(int i=1;i<n;i++) read(b[i]);
	int L=1e9,R=1e9;
	for(int i=1,s=0,si=0;i<=n;i++)
	{
		Sumb[i]=Dec(Mul(i,s),si);
		s=Add(s,b[i]); si=Add(si,Mul(b[i],i));
		L=min(L,-Sumb[i]/i-1);
		R=min(R,(i*100-Sumb[i])/i+1); 
	}
	int x,q;
	read(q);
	while(q--)
	{
		read(x);
		if(x<L) print(AnsMax);
		else if(x>R) print(0);
		else print(Calc(x));
		puts("");
	}
	return 0;
}
/*
瑶草一何碧,春入武陵溪。溪上桃花无数,花上有黄鹂。我欲穿花寻路,直入白云深处,浩气展虹霓。只恐花深里,红露湿人衣。
坐玉石,欹玉枕。拂金徽。谪仙何处,无人伴我白螺杯。我为灵芝仙草,不为朱唇丹脸,长啸亦何为。醉舞下山去,明月逐人归。
*/

世界树 /「APIO2016」 烟火表演

\(~~~~\) 放弃。

posted @ 2023-02-24 21:56  Azazеl  阅读(25)  评论(0编辑  收藏  举报