• [FZYZOJ 2162] Zrn神犇之折纸游戏


    P2162 -- Zrn神犇之折纸游戏

    时间限制:2000MS

    内存限制:524288KB

    Description

    Zrn神犇最近喜欢上一款折纸游戏,因此他几乎每天都拿着一条悠长悠长又寂寥的纸带折来折去。其具体规则是这样的:

    这是一个长度为N,宽度为1的纸条,从1开始写着连续的N个自然数。

    1 2 3 4 5 6 N

    如果它的长度为偶数,Zrn神犇则会很高兴,直接把它从左往右或从右往左对折。比如长度为6的纸条从左往右对折完就会是这样:

    如果它的长度为质数,Zrn神犇则会觉得不太爽,他就只能把最左端的往右折或把最右端的往左折。比如长度为5的纸条从右往左折完会变成这样:

    如果它的长度是合数,Zrn神犇则会找到它最小的质因数k,把它分成相同长度的k段,按折长度为k的纸条的方法处理。

    Zrn神犇就一遍又一遍地按着这个方法折,最后把这个纸条折成了一个叠在一起的小方块。

    下面演示长度为15,对折和长度为质数时均从右往左折的纸条的折法:(描述可能不大清楚,请见谅)

    (长度为15)

    (长度为10)

    (长度为5)

    (长度为4)

    (长度为2)

    (长度为1,目标状态)

    Input Format

    三个数n,p1,p2,n为纸条的长度,若p1=1,对折时从左往右折,若p1=2,对折时从右往左折;若p2=1,长度为质数时折最左端,若p2=2,长度为质数时折最右端。

    Output Format

    N行,每行一个整数,为1~n的一个排列,表示目标状态从上到下纸片的编号。

    Sample Input

    15 2 2

    Sample Output

    2
    12
    9
    8
    13
    3
    4
    14
    7
    6
    15
    5
    10
    11
    1

    Hint

    对于20%的数据,n≤40;

    对于50%的数据,n≤1000;

    对于100%的数据,n≤5000000。

    【题解】本来一看模拟,被数据范围吓傻了

    然后经过了WZT、CYX大聚聚的教导

    终于明白了-这是一题双链表。

    然后就按照题目操作一下

    憋了半个多小时,发现素因子被我筛错了……

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 const int MAX=5000010;
     4 int n,p1,p2,pr[MAX],head[MAX],next[MAX][2];
     5 int bgn,end,len;
     6 int main() {
     7     scanf("%d%d%d",&n,&p1,&p2);
     8     // p[i]: i的最大素数因子
     9     // 如果i为素数,那么p[i]=i; 反之成立 
    10     for (int i=2;i<=n;++i)
    11         if (pr[i]==0) {
    12             pr[i]=i;
    13             for (int j=i*2;j<=n;j+=i)
    14                 if(pr[j]==0)pr[j]=i;
    15         }
    16     bgn=1;end=len=n;
    17     for (int i=1;i<=n;++i)
    18         head[i]=i, next[i][0]=next[i][1]=0;
    19     while(len!=1) {
    20         int sxbk=len/pr[len];
    21         if (len&1?p2==1:p1==1) {
    22             for (int j=bgn+sxbk-1,k=bgn+sxbk;j>=bgn;--j,++k) {
    23                 next[head[k]][k&1]=head[j];
    24                 next[head[j]][j&1]=head[k];
    25                 head[k]=j;
    26             }
    27             bgn+=sxbk;
    28         }
    29         else {
    30             for (int j=end-sxbk+1,k=end-sxbk;j<=end;++j,--k) {
    31                 next[head[k]][k&1]=head[j];
    32                 next[head[j]][j&1]=head[k];
    33                 head[k]=j;
    34             }
    35             end-=sxbk;
    36         }
    37         len-=sxbk;
    38     }
    39     for (int i=head[bgn];i;i=next[i][head[bgn]&1]) 
    40         printf("%d
    ",i);
    41     return 0;
    42 }
    View Code
    这篇文章由TonyFang发布。 所有解释权归TonyFang所有。 Mailto: tony-fang@map-le.net
  • 相关阅读:
    C语言 · 最小公倍数
    SSH实战 · SSH项目开发环境搭建
    C语言 · 回文数
    C语言 · 特殊回文数
    C语言 · 查找整数
    SSH实战 · SSH项目中怎么玩验证码
    SSH实战 · JAVA发送邮件相关
    SSH实战 · AJAX异步校验
    C语言 · 打印1-200之间的素数
    Jenkins权限设计错误解决办法
  • 原文地址:https://www.cnblogs.com/TonyNeal/p/fzyzoj2162.html
Copyright © 2020-2023  润新知