出题三

T1

签到题,无原。

\(T\) 为最终的字符串,\(n\) 为字符串 \(S\) 的长度。为了方便计数,我们钦定 \(S\) 的每一位尽可能向 \(T\) 的后面匹配。对于匹配到的每一位,我们分开考虑,假设当前 \(S\) 的第一位匹配到了 \(T\) 的第 \(i\) 位。

对于第 \(i\) 位之前,显然可以任意填,方案为 \(26^{i-1}\);对于 \(S\) 的剩下 \(n-1\) 位,方案数为 \(C_{n+k-i}^{n-1}\);对于最后匹配的位置,由于我们钦定每一位尽可能向后面匹配,所以剩下没填的位置都不能和它上一个填过的位置重合,方案数为 \(25^{k-i+1}\)。最终答案即为:

\[\sum_{i=1}^{k+1} 26^{i-1}C_{n+k-i}^{n-1}25^{k-i+1} \]

#include<bits/stdc++.h>
#define int long long
using namespace std;
const int mod=998244353;
const int N=2e6+10;
int inv[N],fac[N],k,n,ans;
char s[N];
inline int ksm(int a,int b) {
	int res=1;
	while(b) {
		if(b&1) res=res*a%mod;
		b>>=1;a=a*a%mod;
	}
	return res;
}
inline void init() {
	n=strlen(s+1);fac[0]=inv[0]=1;
	for(int i=1;i<N;++i) fac[i]=i*fac[i-1]%mod;
	inv[N-1]=ksm(fac[N-1],mod-2);
	for(int i=N-2;i>=1;--i) inv[i]=inv[i+1]*(i+1)%mod;
}
inline int C(int a,int b) {return fac[a]*inv[b]%mod*inv[a-b]%mod;}
signed main() {
	scanf("%lld %s",&k,s+1);init();
	for(int i=1;i<=k+1;++i) ans+=ksm(26,i-1)*C(n+k-i,n-1)%mod*ksm(25,k-i+1)%mod,ans%=mod;
	cout<<ans;
	return 0;
}

T2

原 P11390。

子任务一

暴力模拟。

子任务二

这部分和正解没什么关系。

由于值域很小,所以我们可以发现:区间长度为 \(\frac{k(k-1)}{2}\)
证明:由于只有 \(k\) 种数,每种数的出现次数不能相同,所以每个数出现次数总和为 \(1+2+...+k\),也就是 \(\frac{k(k-1)}{2}\)。双指针维护一下即可。

子任务三

这部分是启发正解的。

对于一个数 \(a_i\),我们设 \(pre_i\) 表示 \(a_i\) 上一次出现的位置,则区间 \((pre_i,i]\) 产生贡献,区间 \(+1\);区间 \((pre_{pre_i},pre_i]\) 贡献消失,区间 \(-1\)。显然可以线段树优化,将题目转化为区间加、查询全局非 \(0\) 个数。

子任务四

我们重新转化一下题意:

\(S_i\) 表示存在出现恰好 \(i\) 次的数的线段集合,我们要求的即为 |\(S_1 \cap S_2 \cap... \cap S_k|\)

思考一下子任务三时我们的做法:区间加、区间查非 \(0\) 数的个数。可以发现这就是矩形面积并。此时题目就相当于求 \(k\) 个矩形面积并的交,容斥一下即可。

#include<bits/stdc++.h>
using namespace std;
const int N=1e5+10;
inline int read() {
	int s=0,x=1;char ch=getchar();
	while(!isdigit(ch)) {if(ch=='-') x=-1;ch=getchar();}
	while(isdigit(ch)) s=(s<<3)+(s<<1)+(ch^48),ch=getchar();
	return s*x;
}
struct info{int mi,cnt;};
inline info operator +(info f,info g) {
	info res={0,0};res.mi=min(f.mi,g.mi);
	res.cnt+=(f.mi==res.mi)*f.cnt+(g.mi==res.mi)*g.cnt;
	return res;
}
int n,a[N],k,lst[N],pre[N];
long long ans;
struct SEG{
	info tr[N<<3];int tag[N<<3];
	#define mid ((l+r)>>1)
	#define ls p<<1
	#define rs p<<1|1
	inline void pushup(int p) {tr[p]=tr[ls]+tr[rs];}
	inline void pd(int p,int k) {tr[p].mi+=k,tag[p]+=k;}
	inline void pushdown(int p) {pd(ls,tag[p]),pd(rs,tag[p]),tag[p]=0;}
	inline void build(int p,int l,int r) {
		tag[p]=0;if(l==r) {tr[p]={0,1};return ;}
		build(ls,l,mid);build(rs,mid+1,r);pushup(p);
	}
	inline void add(int p,int l,int r,int x,int y,int k) {
		if(l>y||r<x) return ;
		if(l>=x&&r<=y) {pd(p,k);return ;}
		pushdown(p);add(ls,l,mid,x,y,k);add(rs,mid+1,r,x,y,k);pushup(p);
	}
	inline int qry() {return tr[1].mi?n:n-tr[1].cnt;}
}t;
int main() {
	n=read();k=read();
	for(int i=1;i<=n;++i) a[i]=read(),pre[i]=lst[a[i]],lst[a[i]]=i;
	for(int j=1,op;j<(1<<k);++j) {
		t.build(1,1,n);op=__builtin_popcount(j);
		for(int i=1;i<=n;++i) {
			int nw=i;
			for(int p=0;p<k;++p) {
				if(j&(1<<p)) {
					t.add(1,1,n,pre[nw]+1,nw,1);
					if(pre[nw]) t.add(1,1,n,pre[pre[nw]]+1,pre[nw],-1);
				}
				nw=pre[nw];if(!nw) break;
			}
			int lt=t.qry();
			ans+=lt*(op&1?1:-1);
		}
	}
	cout<<ans;
	return 0;
}

T3

原 P4922。

其实一堆技能里面有一大半是迷惑你的。

瞬身闪避:不如大招。

燃起来了:不如一刀大斩。

劳大肘击:不如大招。

吓哭超影 \(3000\):表面上看有 \(10s\) 时停,实际上,它会清除持续伤害 \(buff\),牢布打一下就后退打不到了,留尼卡多利原地杵 \(10s\),有啥用?不如大招。

弑神登神:不如大招。

综上所述,只有一刀大斩、大招、通灵螃蟹有用。但此时攻击还是太多了,考虑继续简化。

我们考虑大招的位置,设此时持续伤害 \(buff\)\(i\) 层,减速有 \(j\) 层。

1.大招与一刀大斩结合:
大招在前:\(i \times (j+5+1)+(i+1)(j+1)\)
大招在后:\((i+1)(j+1)+(i+1)(j+5+1)\)

显然大招在后伤害更高。

2.大招与通灵螃蟹结合:
大招在前:\(i \times(j+1+5)+i \times(j+2)\)
大招在后:\(i \times(j+2)+i \times(j+5+2)\)

显然也是大招在后伤害更高。

或者你也可以感性理解:另外两个技能会叠 \(buff\),打游戏平时不都是先叠 \(buff\) 再开大嘛。

这时候就有策略了,我们先使用一刀大斩和通灵螃蟹,再开大。

考虑 \(dp\)。设 \(f_{i,j}\) 表示使用了 \(i\) 次一刀大斩和 \(j\) 次通灵螃蟹的最大伤害,则有转移:

\[f_{i,j}=max(f_{i-1,j}+r \times(i-1)(j+1)+a,f_{i,j-1}+r \times i \times j+c) \]

\(a\) 指一刀大斩伤害,\(c\) 指通灵螃蟹伤害,\(r\) 指持续伤害 \(buff\)

此时时间 \(O(n^2)\),空间滚动数组一下即可 \(O(n)\)

#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=1e4+10;
int a,b,c,ans1,ans2=N,f[2][N],n,hp,atk,r;
signed main() {
	cin>>n>>hp>>atk;atk/=10;
	a=atk*8,c=atk*7;r=atk;
	for(int i=0;i<=n;++i)
		for(int j=0;j<=n-i;++j) {
			b=atk*12+atk*i*(j+6);
			if(i) f[i&1][j]=max(f[i&1][j],f[(i-1)&1][j]+a+r*(j+1)*(i-1));
			if(j) f[i&1][j]=max(f[i&1][j],f[i&1][j-1]+c+r*i*j);
			ans1=max(ans1,f[i&1][j]+(n-i-j)*b);
			if(f[i&1][j]>=hp) ans2=min(ans2,i+j);
			else if(f[i&1][j]+(n-i-j)*b>=hp) ans2=min(ans2,i+j+(hp-f[i&1][j]+b-1)/b);
		}
	ans1<hp?printf("%lld\nhks",ans1):printf("%lld\nLeiZeProMax Nb!!!",ans2);
	return 0;
}

T4

原 P12336。

我知道你想骂我,但是你先别急。

看到根号,先考虑平方。此时式子转化为:

\[a^2+b^2+c^2+d^2=(a \oplus b \oplus c \oplus d)^2 \]

由于 \(a,b,c,d\) 均为正整数,所以有 \(a^2+b^2+c^2+d^2>d\),于是就有 \((a \oplus b \oplus c \oplus d)^2>d\)

\(a \oplus b \oplus c \oplus d=d+x\),那么有

\[(a \oplus b \oplus c \oplus d)^2=(d+x)^2 \]

\[(a \oplus b \oplus c \oplus d)^2=d^2+2dx+x^2 \]

\[a^2+b^2+c^2+d^2=d^2+2dx+x^2 \]

\[a^2+b^2+c^2=2dx+x^2 \]

考虑如何构造一个 \(x\)。不难发现任何一个 \(x\) 都是可以构造的,设 \(y\)\(x\) 二进制下最高位,则我们可以令 \(d\) 的前 \(y\) 位全为 \(0\),此时只需要构造 \(a \oplus b \oplus c=x\) 即可。

为了构造更方便,我们考虑让 \(x\) 尽可能小。\(0\) 肯定不行,所以我们让 \(x=1\),即 \(a \oplus b \oplus c=1\)(当然前提是 \(d\) \(mod\) \(2=0\)),此时上式可以变为:

\[a^2+b^2+c^2=2d+1 \]

此时我们可以表示出 \(d\)

\[d=\frac{a^2+b^2+c^2-1}{2} \]

考虑如何构造出 \(a \oplus b \oplus c=1\),为了接下来方便,我们先特判掉 \(a=1\) 的情况,这个可以直接暴力枚举。
那么此时有 \(a>1\)\(a<b<c\)

考虑异或的性质。显然 \(a,b,c\) 二进制下的最高位不能相同,且 \(b,c\) 最高位相同。

这个时候就需要我们和出题入脑电波交流一下了。我们设 \(k\)\(a\) 在二进制下最高位,令 \(b=a+2^k\),可以发现,此时 \(a \oplus b=2^k+2^{k+1}\),我们再令 \(c=2^k+2^{k+1}+1\),此时我们可以惊奇的发现,\(a \oplus b \oplus c\) 居然成了 \(1\)!并且我们可以发现,这种构造显然满足 \(a<b<c<d\)

但这就完了吗?不,此时我们发现,我们忽略了这种构造的前提条件:\(d\) \(mod\) \(2=0\),代入发现,当 \(a \equiv 0(mod\) \(2)\) 时,此时满足条件;但当 \(a \equiv 1(mod\) \(2)\) 时,并不满足条件。

考虑如何调整构造方案,此时我们再与出题入进行一波脑电波交流。
我们可以发现 \(a \equiv b(mod\) \(2)\)\(c \equiv 1(mod\) \(2)\),当 \(a \equiv 1(mod\) \(2)\) 时,我们将 \(b,c\) 都减 \(1\),此时可以发现:\(a \oplus (b-1) \oplus(c-1)\) 依然等于 \(1\)。此时我们可以发现,我们满足了 \(d\) \(mod\) \(2=0\) 的条件。

构造完毕。总结一下:

1.当 \(a=1\) 时,暴力或者随便找一组解。
2.当 \(a\) \(mod\) \(2=0\) 时,令 \(k\)\(a\) 在二进制下最高位,则 \(b=a+2^k\)\(c=2^k+2^{k+1}+1,d=\frac{a^2+b^2+c^2-1}{2}\)
3.当 \(a\) \(mod\) \(2=1\) 时,\(b=a+2^k-1\)\(c=2^k+2^{k+1}\)

至于无解嘛,你可以发现不存在无解情况。

#include<bits/stdc++.h>
#define int long long
using namespace std;
int a,b,c,d;
signed main() {
	cin>>a;int k=__lg(a);
	if(a==1) {cout<<"4 28 40\n";return 0;}
	if(!(a&1)) b=a+(1ll<<k),c=(1ll<<k)+(1ll<<(k+1))+1,d=(a*a+b*b+c*c-1)/2;
	else b=a+(1ll<<k)-1,c=(1ll<<k)+(1ll<<(k+1)),d=(a*a+b*b+c*c-1)/2;
	cout<<b<<' '<<c<<' '<<d<<'\n';
	return 0;
}
posted @ 2025-09-13 17:55  leizepromax  阅读(33)  评论(3)    收藏  举报