标签:com 顺序 没有 inline 序列 strong href size 题目
题面
原题面:
小 B 面前的桌子上有 \(n\) 个硬币,\(0\) 表示正面,\(1\) 表示反面,只有当这 \(n\) 个硬币都是 \(0\) 朝上的时候这个他才能把这些钱收起来。现在他可以一个这样的操作来翻硬币,他选择一个 \(x\),把 \(1\) 到 \(x\) 位置上的硬币都翻面,他现在想知道最少需要多少次操作能使所有硬币正面朝上
给定一个长度为\(n\)的\(01\)串\(s\),\(s_i \in \{ 0,1 \}\)
每次可以选择一个\(x\),使得\([1,x]\)之间的所有元素反转,即\(0 \rightarrow 1,1 \rightarrow 0\)
问最少需要多少次可以把所有的元素变为\(0\)。
第一行:一个非负整数\(n\),表示串\(s\)的长度。
第二行:串\(s\),第\(i\)个字符表示\(s_i\)
输出最小的操作次数。
4
1001
3
第一次操作:\(x = 4\),串\(s\)变为\(0110\)
第二次操作:\(x = 3\),串\(s\)变为\(1000\)
第三次操作:\(x = 1\),串\(s\)变为\(0000\)
可以证明,最小需要\(3\)次可以将\(s\)中所有元素变为\(0\)。且没有一种方案比这种方案更优。
5
10010
3
第一次操作:\(x = 4\),串\(s\)变为\(01100\)
第二次操作:\(x = 3\),串\(s\)变为\(10000\)
第三次操作:\(x = 1\),串\(s\)变为\(00000\)
可以证明,最小需要\(3\)次可以将\(s\)中所有元素变为\(0\)。且没有一种方案比这种方案更优。
对于\(30\%\)的数据:\(1 \leq n \leq 20\)
对于另\(20\%\)的数据:所有\(s_i\)都相等
对于\(100\%\)的数据:\(1 \leq n \leq 10^6\)
慢慢挖掘题目性质。
性质1:答案与操作的顺序无关
证明:
显而易见,无需证明
设\(p_i\)为\(s\)转化成目标串的过程中,\(s_i\)被反转的最小次数
\(p_i\)一定是非负整数
性质2:
当\(s_i = 0\)时,\(p_i\)一定是偶数;
当\(s_i = 1\)时,\(p_i\)一定是奇数;
证明:
显然,不用证明。
性质3:\(p_1\)就是\(s\)转化为目标串的最小操作次数
证明:
由于每次操作都是\([1,x]\),都动了\(s_1\)。
所以\(s_1\)被反转的次数就是转化为目标串的最小次数。
性质4:\(\forall p_i \geq p_{i + 1} (1 \leq i \leq n)\),即\(p\)单调不增
证明:
对于\(i,j\),\(i < j\)
则\(p_i \geq p_j\)
因为每次动到\(j\)的时候,\(i\)肯定被动到了。
所以\(p_i \geq p_j\)
即,\(p\)单调不增。
***
性质5:\(\max _{1 \leq i \leq n} \{ p_i\} = p_1\)
证明:
由性质4得来。
结合以上所有性质。
目标是要求操作次数最小,所以就是要求\(p_1\)最小。
要求\(p_1\)最小,由于性质5,所以目标就是要求这个序列\(p\)尽量小。
这样才能保证最大的最小。
因为\(p_i\)是非负整数,我们考虑倒推。
并且要保证不破坏以上所有性质。
当\(s_n = 0\)时,显然,\(p_n = 0\)
当\(s_n = 1\)时,显然,\(p_n = 1\)
我们开始递推:
对于第\(i (1 \leq i \leq n-1)\)位
如果\(s_i = s_{i+1}\),则,\(p_i = p_{i+1}\)
如果\(s_i \not ={s_{i+1}}\),则,\(p_i = p_{i+1} + 1\)
***
综上,递推完之后,\(p_1\)就是答案。
代码:
#include<iostream>
#include<cstdio>
#include<string>
#include<cstring>
using namespace std;
#define maxn 1000000
int p[maxn + 10];
int main()
{
int n;
string s;
cin>>n>>s;
if(s[s.size() - 1] == '0')
{
p[s.size() - 1] = 0;
}else
{
p[s.size() - 1] = 1;
}//判断最后一位
for(int i = s.size() - 2;i >= 0;i--)//倒推
{
if(s[i] == s[i + 1])
{
p[i] = p[i + 1];
}else
{
p[i] = p[i + 1] + 1;
}//递推公式
}
cout<<p[0];//输出第一个的p
return 0;
}
复杂度\(\Theta (n)\)
标签:com 顺序 没有 inline 序列 strong href size 题目
原文地址:https://www.cnblogs.com/huoshihongqwq/p/12109634.html