专栏文章
题解:P11959 「ZHQOI R1」诗歌
P11959题解参与者 1已保存评论 0
文章操作
快速查看文章及其快照的属性,并进行相关操作。
- 当前评论
- 0 条
- 当前快照
- 1 份
- 快照标识符
- @mipue54p
- 此快照首次捕获于
- 2025/12/03 18:06 3 个月前
- 此快照最后确认于
- 2025/12/03 18:06 3 个月前
赛时做法,不知道官方题解为什么这么复杂,赶紧来发个题解。
显然一个串是动听的充要条件是任意两个相同字符坐标差超过 ,即任意连续 个字符两两不同。
注意到开头已经给了 个字符,这启示我们直接往后填,不考虑末位字符的限制,每次要求与前面 个字符均不同,有 种方案。
对每种字符进行考虑,如果这个字符在开头 处出现过,则只会在 这一段再次出现,将 任意填上后,转化为一个只与余下长度有关而与当前字符无关的问题。
显然可以不考虑已确定的末位字符 ,然后考虑指定一些位置放 ,显然相邻位置差以及与末位的差都至少为 ,进一步地,如果一个位置之前 位有 ,直接 任意填,否则额外要求与 不同, 种方案。
可以直接 dp, 表示前 位的答案,有转移 。
时间复杂度 ,跑挺快的。
CPP#include<bits/stdc++.h>
#define maxn 2010
#define int long long
using namespace std;
const int Mod=998244353,N=1e7;
inline int reduce(int x){if(x>=Mod) return x-=Mod;return x;}
int q,k,m,f[N+100],bas[maxn];
inline int query(int x){
if(x<0) return 0;
return f[x];
}
inline void solve(){
int res=1;
scanf("%lld%lld%lld",&q,&k,&m);
m+=2;
bas[0]=1;
for(int i=1;i<=m;i++) bas[i]=bas[i-1]*(k-m)%Mod;
f[0]=1;
for(int i=1;i<=N;i++){
if(i>m) f[i]=(f[i-1]*(k-m-1)+f[i-m-1]*bas[m])%Mod;
else f[i]=f[i-1]*(k-m-1)%Mod;
}
while(q--){
int n;
scanf("%lld",&n);
unordered_map<int,int>mp;
for(int i=1,x;i<=m;i++) scanf("%lld",&x),mp[x]=i;
int len,ans=0;
scanf("%lld",&len);
while(len--){
int x;
scanf("%lld",&x);
if(!mp.count(x)) ans=reduce(ans+query(n-m-1));
else ans=(ans+query(n-mp[x]-m-1)*bas[mp[x]])%Mod;
}
printf("%lld\n",ans);
}
}
signed main(){
signed C,T=1;
scanf("%d",&C);
while(T--) solve();
return 0;
}
相关推荐
评论
共 0 条评论,欢迎与作者交流。
正在加载评论...