[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
原文地址:https://www.cnblogs.com/TonyNeal/p/fzyzoj2162.html