**开关灯**
时间限制(普通/Java) : 1000 MS/ 10000 MS 运行内存限制 : 65536 KByte
总提交 : 43 测试通过 : 16
描述
paodekuai学长最近在复习考研题目,这天他被考研题目折磨的死去活来,于是决定做一道水题来放松心情。题目内容如下:有L盏灯编号为1 ~ L,有L个开关编号也为1 ~ L,编号为i的开关决定了编号为i的倍数(含i自身)的灯的状态(每按下开关,对应的灯的状态反转)。现给一个长度为L的字符串代表L盏灯的初始状态,字符串仅有‘Y’和‘N’组成,‘Y’代表开,‘N’代表关。求总共最少需要按几次开关使得所有的的灯被关上。
输入
本题为单组数据评测。
第一行一个整数L (1 ≤ L ≤ 105),表示灯的个数
第二行一个长度为L的字符串,每个字符都是‘Y’或‘N’,表示灯的初始状态。
输出
输出一个整数ans,表示关上所有灯所需的最少操作数(每按下任何一个开关视为一次操作)。
样例输入
9
YNYNYNYNY
样例输出
2
提示
对于所给样例,可以先按一下2号开关,变成状态 YYYYYYYYY, 之后再按下1号开关变成状态NNNNNNNNN,不难证明,不存在操作次数更少的关灯方法。
题目来源
By YG_PP
思路:
这是一个开关灯问题,很清楚地知道每个数只有 0 1 两种状态,按道理来说可以用动态规划来写。可惜我不会=。=
以下是ac代码思路:
因为第 i 盏灯的开关,可以直接影响到 2 * i 及以后所有 i 的倍数的灯的开关情况。所以最优方案只有从头往后的扫,这样就变成一个简单的模拟题了。
以下是ac代码:
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <cstdlib>
using namespace std;
const int maxn=1e5+5;
char s[maxn+5];
int a[maxn+5];
int main()
{
int k;
scanf ("%d",&k);
scanf ("%s",s+1);
int len=strlen(s+1);
for (int i=1;i<=len;i++)//把 Y N 的状态 变成 0 1 状态,也可以不变。
{
if (s[i]=='Y') a[i]=1;
else a[i]=0;
}
long long cnt=0;
for (int i=1;i<=len;i++)
{
if (a[i]==1)
{
cnt++;
a[i] = !a[i];
for (int j=2*i;j<=len;j+=i) a[j] = !a[j];//Eratosthenes 筛法
}
}
printf ("%lld\n",cnt);
}
P.S. 说到底这还是一条简单的语言题,用嘴很容易就能说出来,当时没做出来,到底还是语言不过关。