打字机——线性递推

23 篇文章 0 订阅
6 篇文章 0 订阅

打字机
本题看起来很不好做,但仔细画画图找找规律之后还是能找出规律的
——————————————————————————————————————————————
现在已知以 s [ i ] s[i] s[i]结尾的答案 s u m [ i ] sum[i] sum[i]和总答案,
这时候一个准备加进答案的 d o t h [ j ] doth[j] doth[j]
那么我们发现,总答案的两倍减去 s u m [ i ] sum[i] sum[i]
证明:原来的答案中有以 d o t h [ j ] 结 尾 的 , 也 有 不 以 d o t h [ j ] 结 尾 的 , 因 为 每 个 字 母 都 有 可 能 没 打 到 , 则 有 s u m [ d o t h [ j ] ] 个 不 以 d o t h [ j ] 结 尾 的 , 即 d o t h [ j ] 没 打 到 。 而 这 时 候 在 所 有 的 方 案 后 加 上 d o t h [ i ] , 因 为 有 可 能 打 到 , 也 有 可 能 没 打 到 , 所 以 乘 2 , 而 又 因 为 s u m [ d o t h [ j ] ] 个 答 案 已 算 过 , 所 以 应 减 去 doth[j]结尾的,也有不以doth[j]结尾的,因为每个字母都有可能没打到,则有sum[doth[j]]个不以doth[j]结尾的,即doth[j]没打到。而这时候在所有的方案后加上doth[i],因为有可能打到,也有可能没打到,所以乘2,而又因为sum[doth[j]]个答案已算过,所以应减去 doth[j]doth[j]sum[doth[j]]doth[j]doth[j]doth[i],2sum[doth[j]]
遇到退格,

if(cnt){
			   sum[s[cnt]-'A'+1]++;
			   ans=(ans+1)%mod;
			   cnt--;	
			}

因为在doth中加字母实际上就是没达到字母的方案,已经算过,所以不用管,而原数组中的s[i]是没算过的,所以要加1,而因为退格会对后面贡献新的方案,所以sum要+1

#include<bits/stdc++.h>
using namespace std;

const int N=5000010,mod=0x125E591;
char s[N],doth[N];
int n,m,sum[N];
int main(){
	scanf("%d%d",&n,&m);
	int cnt=n,ans=1;
	scanf("%s %s",(s+1),(doth+1));
	for(int i=1;i<=m;i++)
	{
		if((doth[i]!='u')){
			int tmp=sum[doth[i]-'A'+1];
			sum[doth[i]-'A'+1]=ans;
			ans=((ans*2%mod-tmp%mod)%mod+mod)%mod;
		}
		else{
			if(cnt){
			   sum[s[cnt]-'A'+1]++;
			   ans=(ans+1)%mod;
			   cnt--;	
			}
		}
	}
	printf("%lld",ans);
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值