一道逻辑编程题目。小菜求大神出马
大厅里有100盏灯,每盏灯都编了号码,分别为1-100。每盏灯由一个开关来控制。(开关按一下,灯亮,再按一下灯灭。开关的编号与被控制的灯相同。)开始时,灯是全灭的。现在按照以下规则按动开关。
第一次,将所有的灯点亮。
第二次,将所有2的倍数的开关按一下。
第三次,将所有3的倍数的开关按一下。
以此类推。第N次,将所有N的倍数的开关按一下。
问第N次(N大于等于2,且小于等于100)按完以后,大厅里还有几盏灯是亮的。
求思路加代码 谢谢
[最优解释]
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace _01
{
class Program
{
static int divisor = 2; //除数因子,因为从第二次开始算,所以取2
static int[] lights = new int[100]; //100个灯的数组
static void Main(string[] args)
{
for (int i = 0; i < lights.Length; i++)
{
lights[i] = 1; //初始化所有灯的值为1(任何整数均可,打开就是正的,关了就乘-1
}
int n =100;
int result = count(n); //第100次的结果
Console.WriteLine("第{0}次,大厅里还有{1}盏灯是亮的",n,result);
Console.ReadKey();
}
static int count(int n)
{
if (n >= 2) //从2次起算,1次直接返回100
{
loop(n); //暴力循环,模拟开关n次
int sum = 0;
for (int i = 0; i < lights.Length; i++)
{
if (lights[i]> 0)
{
sum += 1; //把最后循环的结果,遍历一次,大于0的表示灯的状态是开,用sum记录
}
}
return sum;
}
else
{
return 100;
}
}
static void loop(int n)
{
if (n < 2)
{
return;
}
for (int i = 2; i <= 100; i++) //用循环模拟按灯的结果,因为用到灯的序号,所以i从2开始,100结束
{
if (i % divisor == 0) //当i为因素的倍数
{
lights[i-1] = lights[i-1] * -1; //使该灯的值改变一次
}
}
divisor++; //因素加1
loop(n - 1); //继续下一次循环,直到n=2结束
}
}
}
完全的暴力算法,除了递归想不到别的方法了
[其他解释]
private void button1_Click(object sender, EventArgs e)
{
for (int i = 1; i <= 100; i++)
{
entity en = new entity();
en.index = i;
en.flag = true;
allLight.Add(en);
}
cal(4);
}
List<entity> allLight = new List<entity>();
private void cal(int times)
{
for (int i = 2; i <= times; i++)
{
List<entity> allPxNum = allLight.FindAll(x => (x.index % times == 0));
foreach (entity en in allPxNum)
{
en.flag = !en.flag;
allLight[en.index - 1] = en;
}
}
List<entity> allLigthTrue = allLight.Where(x => (x.flag == true)).ToList();
int lightNum = allLight.Where(x => (x.flag == true)).Count();
System.Diagnostics.Debug.WriteLine("还有" + lightNum + "灯亮");
foreach (entity en in allLigthTrue)
{
System.Diagnostics.Debug.WriteLine(en.index + "灯亮");
}
}
public class entity
{
public int index { get; set; }
public bool flag { get; set; }
}
试试
[其他解释]
http://hi.baidu.com/zhiliangshouhe/item/d60660874a4dc7dbd0f8cd54
[其他解释]
那个帖子对吗?如果只有平方的都亮着,那么100以内的质素怎么说?所有的质素只按一次不是吗?
[其他解释]
我看错了,刚开始灯全亮啊,汗
[其他解释]
int[100] light ;
int rst=0;//结果
for(int i=1;i<=100;i++){
light[i-1]=1;//亮
} int N;//N为次数
if(N=1){
rst=100;
}
for(int j=2;j<=N){
for(int i=1;i<=100;i++){
if(i%j==0){
if(light[i-1]==1)
{light[i-1]=0}
else
{light[i-1]=1}
}
}
}
for(int i=1;i<=100;i++){
if(light[i-1]=1){
rst+=1;
}
}
只提供个思路,怎么写还得看楼主的。。
[其他解释]
数学学的不好,最简单的办法就是双重循环,定义一个长度为100的bool数组,
外层是i=1;i<=n;i++,
里层是j=0;j<100;j=j+n
然后循环里对数组的值反转
arr[j]=!arr[j]
[其他解释]
+1
代码
static void GetLightNums(int n)
{
for (int i = 1; i * i <= n; ++i) Console.Write(i * i + " ");
}
[其他解释]
我也来贴一下我的代码:
public static bool IsPrime(int n)
{
if (n == 2) return true;
if (n < 2
[其他解释]
n % 2 == 0) return false;
for (int i = 3; i < Math.Sqrt(n); i++)
{
if (n % i == 0) return false;
}
return true;
}
public static int GetLightRemainingCount(int lightCount, int filterCount)
{
if (filterCount < 1) throw new ArgumentException();
if (filterCount == 1) return lightCount;
var lights = new bool[lightCount + 1];
Parallel.For(0, lightCount + 1, i => lights[i] = true);
for (int filter = 2; filter <= filterCount; filter++)
{
if (!IsPrime(filter)) continue;
for (int i = 1; i <= lightCount; i += filter)
{
lights[i] = false;
}
}
return lights.Where(light => light == true).Count() - 1;
}
说明:
第一个 IsPrime 是判断是不是素数。为什么要判断?一个个循环去除 1 ~ N 个倍数因子,显然是不合适的,然后发现,如果要过滤的话,第一次就把偶数给全部排除了。从第二次开始,其实如果不是素数的因子可以全部忽略!无需去用剩下的每一个Index 去除因子。然后每次遇到一个倍数因子,就从该因子开始向后以其倍数增长。
举个例子,如果当前因子是 15,因为 15 不是素数,所以直接忽略,为什么?因为 15 = 3 * 5,3 和 5 的倍数都已经排除了,更何况 15,所以直接忽略。
如果当前因子是 7,那就以 7 的倍数为 for 循环的步长来增长,将该素数的倍数对应的 light 全部 turn off 掉。
这是我的一些想法。
[其他解释]
readonly bool[] lights = new bool[100];
private void pressOnce(int press)
{
for (int currentCount = press; currentCount < 100; currentCount = currentCount + press)
{
lights[currentCount - 1] = !lights[currentCount - 1];
}
}
//按第一次时也可调用该函数,press为第几次调用(第几次按)
[其他解释]
Dim i As Integer = 0
Dim a(99) As Object
Dim f As Boolean
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
If i = 0 Then '第一次的时候开灯
For j As Integer = 0 To a.Length - 1
a(j) = True
Next
ElseIf i > 0 Then
For j As Integer = 0 To a.Length - 1
If (j + 1) Mod (i + 1) = 0 Then
If a(j) = True Then
a(j) = False
Else
a(j) = True
End If
End If
Next
End If
Dim strMsg As String = String.Empty
Me.ListBox1.Items.Clear()
For j As Integer = 0 To a.Length - 1
If a(j) = True Then
strMsg = "第" & j + 1 & "盏灯是亮的"
Else
strMsg = "第" & j + 1 & "盏灯是灭的"
End If
Me.ListBox1.Items.Add(strMsg)
Next
i = i + 1
End Sub
[其他解释]
我贴下我的代码,忘大家轻拍,变量命名的不是很好
static class Program
{
/// <summary>
/// 应用程序的主入口点。
/// </summary>
[STAThread]
static void Main()
{
Console.WriteLine("输入x退出,");
while (true)
{
Console.WriteLine("请输入经过N次,N为1-100之间的数:");
string wReadLine = Console.ReadLine();
if (wReadLine == "X"
[其他解释]
wReadLine == "x")
break;
int N;
if (int.TryParse(wReadLine, out N))
{
Bulb wBult = new Bulb();
for (int i = 1; i <= N; i++)
wBult.TurnLightOn(i);
wBult.CountBult();
}
else
{
Console.WriteLine("输入N的数据格式不正确");
}
Console.WriteLine("\t\n");
}
}
}
class Bulb
{
bool[] mBulb = new bool[100];
public void TurnLightOn(int label)
{
if (!(label >= 1 && label <= 100))
Console.WriteLine("输入的N不在1-100内");
List<int> wLabelList = new List<int>();
for (int i = 1; ; i++)
{
if (i * label > 100)
break;
wLabelList.Add(i * label);
}
for (int i = 0; i < wLabelList.Count; i++)
{
mBulb[wLabelList[i] - 1] = !mBulb[wLabelList[i] - 1];
}
}
public void CountBult()
{
int wNum = 0;
for (int i = 0; i < 100; i++)
{
if (mBulb[i])
wNum++;
}
Console.WriteLine("还有{0}盏灯亮着", wNum);
}
}
TurnLightOn方法是输入执行某一次 灯的状态改变,CountBult是数出还有几盏灯亮着