-
[1624] 死胡同
- 时间限制: 1000 ms 内存限制: 65535 K
- 问题描述
- 一个死胡同由排成一列的 n 个格子组成,编号从 1 到 n 。
实验室的“猪猪”一开始在1号格子,开始向前走,每步一格,并且每走 k
步会在当前的格子上打上记号(开始时,1号格子也有记号)。由于这是死胡同,每当“猪猪”走到最左或者最右的格子时,它会改变方向。好奇的“猪猪”在想:
如果我一直走,能否把所有格子都打上记号呢?聪明的你一定知道答案!
Hint1:如果 n=6,k=2,位置变化为:1 -> 3 -> 5 -> 5 -> 3 -> 1 -> 3 -> 5 .... 显然,此时不能将所有格子打上标记。(如下图)
- 输入
- 多组输入数据(组数<=100)
每组数据一行,包含两个正整数 n 和 k。
(1 <= n <= 100000 , 1 <= k <= 100000) - 输出
- 对于每组数据输出一行 YES 或者 NO 代表能否给所有格子打上标记。
- 样例输入
-
6 2 6 3
- 样例输出
-
NO YES
- 提示
-
无
- 来源
-
2015苏州大学ACM-ICPC集训队选拔赛(1)
题目大意: 题目讲的很清楚,不过要注意 k 是可以大于n 的 因为这个 我RE了几发。这个 有人用了搜索写出来的,,我不是用搜索,所以我这里的代码跟搜索没多大关系。
我的思路就是 设置一个数组,比如是记录朝右行走过的点,那么如果你下次还是朝右走,而且这个点已经走过了,那说明已经进入死循环 可以退出了,这样可以减少很多的时间。
上代码:
1 #include <stdio.h> 2 #include <string.h> 3 #include <math.h> 4 int vis[100010],star[100010]; //定义一个访问过的数组,还有一个就是 朝右走的访问标记 5 int main() 6 { 7 int n,m; //点的个数,还有一次走几格 8 while(~scanf("%d%d",&n,&m)) 9 { 10 if ( n == 1 ) //如果n == 1 那么肯定可以全部访问 11 { 12 printf("YES\n"); 13 continue; 14 } 15 memset(vis,0,sizeof(vis)); //初始化 16 memset(star,0,sizeof(star)); 17 int res = 1; 18 int l = 1; 19 vis[1] = 1; //起始点在1,所以直接访问过, 20 int flag = 1; 21 while (1) 22 { 23 if (l < 1) 24 { 25 flag = 1; 26 l = 2 - l ; 27 } 28 if (l > n ) 29 { 30 flag = -1; 31 l = 2 * n - l; //这个可以自己计算,为何这样,,这边减了之后,依旧可能比1小的,所以下面有一个判断。 32 } 33 if (l < 1) 34 { 35 flag = 1; 36 l = 2 - l ; 37 } 38 if (vis[l] != 1 ) //没访问过 39 { 40 vis[l] = 1; 41 res ++; 42 } 43 if ( (star[l] == 1 && flag == 1) || (flag == -1 && l == 1) ) //如果一个方向上的点,走了第二次 说明进入死循环 可以退出 44 { 45 break; 46 } 47 if ( flag == 1) //记录朝右走过的点 48 { 49 star[l] = 1; 50 } 51 if ( res == n ) 52 { 53 break; 54 } 55 if (flag == 1 ) 56 { 57 l += m % (2 * n - 2); // 2*n - 2 这个规律不难发现,我是画一下图,就知道了 就是一个循环,就是下次走到这个点,并且走的方向是相同的 58 continue; 59 } 60 else if (flag == -1) 61 { 62 l -= m % (2 * n - 2); 63 continue; 64 } 65 //printf("%d\n",l); 66 } 67 if (res == n ) 68 { 69 printf("YES\n"); 70 } 71 else if(res != n) 72 { 73 printf("NO\n"); 74 } 75 } 76 return 0; 77 }
时间: 2024-10-18 14:46:59