CF176B题解
Description
给你两个字符串,问你是否可以用恰好 次使第一个字符串前面任意部分移到后面的操作,让其变为第二个字符串。
Method
The essence of demand
如果题目中是有方法可以将第一个字符串转变成第二个字符串的话,那么如果将这两个字符串想像成两个环的话,这两个环应该是相同的,因为题目中的改变的本质就是改变环的起始点。
Idea
这道题比较难想(至少我是看了题解的DP状态才想到的)。
我们首先考虑只有一次操作的时候,这时候答案很显然是前一个字符串所有前面移到后面能成为第二个字符串的次数。
然后考虑有两次操作的时候,这时候有两种情况:
1.将第一个字符串的前面部分通过两次后移成为第二个字符串。
2.将第一个字符串先通过一次转移成为第二个字符串,再将已经成为第二个字符串的字符串做一个不会改变字符串的转换即可。
做到这里,我相信你们已经有了思路,对于一次成功变换他有两种情况一种是从不同到相同,一种是从相同到相同,所以我们只要维护这两种情况的方案即可完成转移,而由于第 次的操作方案数只与第 次操作完全相关,所以这个操作是没有后效性的,所以可以用DP。
Realization
DP state transition equation
Explanation
---字符串变为目标字符串的方案数。
---字符串变为非目标字符串的方案数
---一次操作能将一个字符串改变成第二个目标字符串的方案数。
---前面一次不是目标字符串,有 种方法可以将不是目标的变为目标的。故如此。
---前面一次是目标字符串,这时候要注意因为 种方法里是有一种以前一个的起始点为起始点的,因为前面一个是满足为目标字符串的,所以要去掉那种情况。
---有 种方法可以变为目标字符串,总方法数为 ,故无法转换的方案数为 。
---与文同理,也要去掉与前面一次操作重合的情况。
Code
#include<bits/stdc++.h>
using namespace std;
string s,s1,s2;
long long jt,n,Q,MOD,i,j,sum,sum1,sum2,sum3,f[100010][3];
bool flag;
int main()
{
ios::sync_with_stdio(0);cin.tie();cout.tie();
cin>>s1;
cin>>s2;
cin>>Q;MOD=1000000007;
n=s1.size();
for (i=1;i<=n;i++)
{
flag=true;jt=0;
for (j=i;j<n;j++)
if (s1[j]!=s2[jt])
{
flag=false;break;
}
else jt++;
for (j=0;j<i;j++)
if (s1[j]!=s2[jt])
{
flag=false;break;
}
else jt++;
sum+=flag;
}
if (s1==s2) f[0][0]=1;
else f[0][1]=1;
for (i=1;i<=Q;i++)
{
f[i][0]=(f[i-1][1]*sum % MOD+f[i-1][0]*(sum-1) % MOD) % MOD;
f[i][1]=(f[i-1][0]*(n-sum) % MOD+f[i-1][1]*(n-sum-1) % MOD) % MOD;
}
cout<<f[Q][0]<<endl;
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· Manus爆火,是硬核还是营销?
· 一文读懂知识蒸馏
· 终于写完轮子一部分:tcp代理 了,记录一下