NOJ——1624死胡同(胡搞模拟)

  • [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)
  • 此题在上学期做过,当时比较naive也是想模拟思路是到头了用reverse数组反转过来再走,然后就机智地TLE了。突然想回来做做这题,当然还是模拟,思路是到头了继续走至超出范围,然后将当前pos对称回来,有种折叠的感觉...事实证明方法可行,但是一交TLE,10W的循环量怎么会TLE?然后找半天找到了几组数据:4 99999,类似于这种k很大n很小的情况下。while里面的while会循环巨多次,此时估计数据量上千万甚至更高然后咋办呢,就开一个结构体数组记录这个点向左走和向右走时是否经过这个点。假设一个点向左走次数或向右走的次数大于等于2,那么这个点在对应的方向被经过了至少两次,可以判断这组数据是走不出来的——只有走不出来的数组才会在某个点重复走来走去。否则让它循环完。

    最后膜拜一下那个0ms代码长度还只有300+的。估计是数学方法吧,吾等智商不够又懒...强行模拟好了

    代码:

     

    #include<iostream>
    #include<algorithm>
    #include<cstdlib>
    #include<sstream>
    #include<cstring>
    #include<cstdio>
    #include<string>
    #include<deque>
    #include<stack>
    #include<cmath>
    #include<queue>
    #include<set>
    #include<map>
    using namespace std;
    typedef long long LL;
    #define INF 0x3f3f3f3f
    struct info
    {
    	int a;
    	int b;
    };
    info pos[100010];
    int main(void)
    {
    	int n,k,i,res;
    	while (~scanf("%d%d",&n,&k))
    	{
    		memset(pos,0,sizeof(pos));
    		if(k==1||n==1)//特判
    		{
    			puts("YES");
    			continue;
    		}	
    		int moni=0;//模拟循环量
    		bool flag=0;
    		int chushi=1;//初始位置
    		int cheng=1;//向左/右走
    		int cnt=0;//走过的路个数(不重复)
    		while (moni<=100010)
    		{			
    			chushi+=cheng*k;
    			while(chushi>n||chushi<1)
    			{
    				if(chushi>n)
    				{	
    					cheng=-1;			
    					chushi=n-(chushi-n);										
    				}	
    				if(chushi<1)
    				{
    					cheng=1;
    					chushi=2-chushi;					
    				}	
    			}
    			if(pos[chushi].a>=2||pos[chushi].b>=2)//重复走过,标记后break
    			{
    				flag=0;
    				break;
    			}
    			if(cheng==1)//继续正着走
    			{
    				if(pos[chushi].a==0)
    				{
    					cnt++;					
    				}
    				pos[chushi].a++;					
    			}
    			else//反着走
    			{
    				if(pos[chushi].b==0)
    				{
    					cnt++;			
    				}
    				pos[chushi].b++;
    			}				
    			if(cnt==n)//模拟量到达,break
    			{
    				flag=1;
    				break;
    			}			
    			moni++;			
    		}
    		if(flag)
    		{
    			puts("YES");
    		}
    		else
    		{
    			puts("NO");
    		}
    	}
    	return 0;
    }
    

     

      

     

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值