夏日祭的灯笼

题目描述

forever97准备举办一场夏日祭,他邀请了许多参展商,并为每位参展商各准备了一串灯笼。
灯笼串可以表示为一个长度为n的字符串,其中每个字符表示一个小灯笼,共有10种小灯笼,分别用0到9表示。
每家参展商都对灯笼串有一定要求,所有符合第 k 家参展商要求的灯笼串所构成的集合,被称为 S[k] 。S[k] 内的任意元素 s ,必须满足以下要求:
1.若 s 的长度 n=1,则 s 仅包含一个数字 d ,d=k%10;
2.若 s 的长度 n>1 且 n 为偶数,则 s(1,n/2)∈S[k+1],s(n/2+1,n)∈S[k];
3.若 s 的长度 n>1 且 n 为奇数,则 s(1,(n-1)/2)∈S[2k],s((n+1)/2, (n+1)/2)∈S[k],s((n+1)/2+1, n)∈S[2k];
*其中 s(l,r) 表示从字符串 s 的第 l 个字符到第 r 个字符所构成的子串,编号从1开始计数。
*其中 x∈S[y] 表示元素 x 属于集合 S[y],即 x 满足第 i 家参展商的美观要求。
给定一串由字符串表示的灯笼串 a,请问需要替换其中几个灯笼,才能符合第k家参展商的要求?

分析

这道题看起来比较难做,但从要求来看,可以发现对于第 k k k家的参展商,其所对应的字符串是唯一的
于是这这就变成一个递归构造的题目,而且题目中的三个要求便是递归中的条件和边界
而递归中的参数,也很好表示,第一个便是 n n n,此处的 n n n相较于题目中的,含义则变成了当前构造的字符串的长度, k k k是当 n = 1 n=1 n=1时当前位上的字符,然后再加一个 l l l,代表当前构造的起始位置
于是,
1.若 s 的长度 n=1,则 s 仅包含一个数字 d ,d=k%10;
的代码实现为

if (n==1) 
{
	ans[l]=k%10+'0';
	return;
}
2.若 s 的长度 n>1 且 n 为偶数,则 s(1,n/2)∈S[k+1],s(n/2+1,n)∈S[k];
3.若 s 的长度 n>1 且 n 为奇数,则 s(1,(n-1)/2)∈S[2*k],s((n+1)/2, (n+1)/2)∈S[k],s((n+1)/2+1, n)∈S[2*k];
的代码实现为
	if (n%2)//当n为奇数时
	{
		dfs((n-1)>>1,k<<1,l);
		ans[l+(n-1)/2]=k%10+'0';//因为题目要求中的l为1,所以题目中的式子就合并为(n+1)/2了
		dfs((n-1)>>1,k<<1,l+(n+1)/2);//长度为n-(n+1)/2-1+1,即(n-1)/2
	}
	else//当n为偶数时
	{
		dfs(n/2,k+1,l);
		dfs(n/2,k,l+n/2);
	}

要注意左移的运算顺序在加减的后面
(刚重构代码时调了好久才发现是这个错误)
然后再与输入的s字符数组逐位比较,输出不同的位数即可

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define ll long long
using namespace std;
char ans[200200],s[200200];
ll n,m,i,j,k,l,o,p;
void dfs(ll n,ll k,ll l)
{
	if (n==1) 
	{
		ans[l]=k%10+'0';
		return;
	}
	if (n%2)
	{
		dfs((n-1)>>1,k<<1,l);
		ans[l+(n-1)/2]=k%10+'0';
		dfs((n-1)>>1,k<<1,l+(n+1)/2);
	}
	else
	{
		dfs(n/2,k+1,l);
		dfs(n/2,k,l+n/2);
	}
}
int main()
{
	scanf("%lld%lld",&n,&k);
	dfs(n,k,1);
	scanf("%s",s);
	for (i=1;i<=n;i++)
	 if (s[i-1]!=ans[i]) l++;
	printf("\n%lld\n",l);
}```

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值