2076. The Drunk Jailer

Problem

A certain prison contains a long hall of n cells, each right next to each other. Each cell has a prisoner in it, and each cell is locked.

One night, the jailer gets bored and decides to play a game. For round 1 of the game, he takes a drink of whiskey, and then runs down the hall unlocking each cell. For round 2, he takes a drink of whiskey, and then runs down the hall locking every other cell (cells 2, 4, 6, ...). For round 3, he takes a drink of whiskey, and then runs down the hall. He visits every third cell (cells 3, 6, 9, ...). If the cell is locked, he unlocks it; if it is unlocked, he locks it. He repeats this for n rounds, takes a final drink, and passes out.

Some number of prisoners, possibly zero, realizes that their cells are unlocked and the jailer is incapacitated. They immediately escape.

Given the number of cells, determine how many prisoners escape jail.

Input

The first line of input contains a single positive integer. This is the number of lines that follow. Each of the following lines contains a single integer between 5 and 100, inclusive, which is the number of cells n.

Output

For each line, you must print out the number of prisoners that escape when the prison has n cells.

Sample Input

2
5
100

Sample Output

2
10



Source: Greater New York 2002

脑子比较笨用的是最北的遍历方法。代码如下:

 1 #include <stdio.h>
 2 #include <string.h>
 3 
 4 int cell[101];//0表示牢房锁闭,1为打开状态
 5 
 6 int main () 
 7 { 
 8     int n;
 9     scanf("%d",&n);
10     
11     int num;
12     int unlockCount;
13 
14     int i,j;
15 
16     while(n--)
17     {
18         unlockCount=0;
19         memset(cell,0,101*sizeof(int));
20 
21         scanf("%d",&num);
22         for(i=1;i<=num;i++)
23         {
24             for(j=i;j<=num;j+=i)
25             {
26                 if(cell[j] == 0)
27                     cell[j]=1;
28                 else
29                     cell[j]=0;
30             }
31         }
32         for(i=1;i<=num;i++)
33             if(cell[i] == 1)
34                 unlockCount++;
35         printf("%d
",unlockCount);
36     }
37     return 0;
38 }

看到网上还有许多其他解法,一并参考下:

1、转载自:http://blog.csdn.net/sinchb/article/details/8075949

    最笨的方法,就是列一个长度为n的数组代表cell是locked还是unlocked,然后按照游戏方法,遍历n次该数组,不断改变数组中的值,这样时间复杂度是O(n*n)。但是经过观察发现,一个cell被开关的次数其实是有规律的,也就是这个cell的编号n的约数的数量;比如4,他的约数有1,2,4,所以编号为4的cell会在游戏的第1,2,4轮被开/关。又如果一个cell被开/关的最终次数为偶数次,则该cell最终也就是关闭的,这个cell里可怜的prisoner将无法上演《越狱》,只有cell编号的约数数量为奇数的,才有机会逃跑。所以,问题转换为,求一个数1~n中,有多少数有奇数个约数。
 1 #include <stdio.h>
 2 int main()
 3 {
 4     short unsigned cell[101] = {0,1,1,1,2,2},i = 0,j,top,sum = 0;
 5     int N,n;
 6     for(i = 6;i <= 100;i++)
 7     {
 8         sum = 0;
 9         top = i>>1;
10         for(j = 2;j <= top ;j++)
11             !(i % j) ? sum++ :0;
12         cell[i] = cell[i-1] + sum%2;
13     }
14     scanf("%d",&N);
15     while(N--)
16     {
17         scanf("%d",&n);
18         printf("%d
",cell[n]);
19     }
20     return 0;
21 }

2、转载自:http://zhidao.baidu.com/link?url=4SkSUEHqhMhNniqchgFztGMNMemf8zP-UgP_ZTVE4TqAqfIGYF-UM8z4m_wHaoOhJLC-ILQUGk5ofRY2GfNEEK

代码比较简洁

编号为1的门只为1的倍数,所以只执行了一次操作,所以其最后的状态是开,编号为2的门只为1和2的倍数,执行了两次操作,其最后的状态是关,编号为3的门为1和3的倍数,执行了三次操作,其最后的状态为关,编号为4的门为1、2、4的倍数,执行了三次操作,其最后的状态为开......以此类推,如果编号为一个数的平方数,则其执行操作的次数为奇数次,其最后的状态为开。于是只要求出小于这个数的正整数中有几个数是平方数即可。

 1 #include<stdio.h>
 2 #include<math.h>
 3 int main(void){int n, a, on;
 4     scanf("%d",&n);
 5     while(n--){
 6         scanf("%d",&a);
 7         on=(int)sqrt(a);
 8         printf("%d
",on);
 9     }
10     return0;
11 }
原文地址:https://www.cnblogs.com/yushuo1990/p/4341155.html