[北京集训测试赛(三)]灯(Light)-奇怪乱搞数学题-素数

Problem 灯

题目大意

n盏灯排成一列,标号一到n,一开始标号为1的灯亮着。

现在依次对于2~n的每一个质数pi,指定一盏亮着的灯ai,点亮所有标号为$A[i]\pm kP_i$的灯。

有spj,任意一种方案即可。

输入一个整数n,输出点灯方案。

Solution

首先写个暴力,考虑一下小范围的数据。

我们发现$n<16$的时候没有完美解,都是n-1。再算下去,发现$n>16$的时候任意一组都有完美解。

我们分析一下这个玩意儿。

把一到n的灯集体下标前移1,变成0~n-1。这时候当我们点亮第一盏灯,所有偶数都被点亮了。

接下来我们从前面的打表知道,如果所有灯都在1点亮,那么只有2不会亮。前移了以后就是只有1不会亮。

这时候我们要想一下怎么点亮这个一。

现在若找到两个质数$P_i<P_j$,使得$P_i^2>=n\&P_i+P_j<n\&P_j=kP_i+1$

一开始绝对已经点亮了pi+1,因为其是偶数。

在pj位置时选择pi+pj标号的即可。

证明:

所有不为$P_i^{A_i}*P_j^{A_j}$的标号一定被点亮过。

因为$P_i^2>n$,所以受影响的标号只有1,pi,pj.

其中,因为$P_j=kP_i+1$

1在pi时被点亮,pi在pj时被点亮,pj在pi时被点亮。

至此,我们搞定了1且没有影响到其它。

这种方法对于n不为26..34时有效,这一些就暴力手算好了,不难。

对于小于16的情况进行特判即可。

AC Code

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstring>
 4 #include <algorithm>
 5 using namespace std;
 6 const int cheat[11][15]={
 7 {0,1,1,4,5,7,7,25,25,25},
 8 {0,1,1,4,5,7,7,25,25,25},
 9 {0,1,1,4,5,7,7,25,25,25},
10 {0,1,1,4,5,7,7,19,27,29,29},
11 {0,1,1,7,13,2,1,1,27,3,1},
12 {0,1,1,1,4,13,1,3,31,31,1,1},
13 {0,1,1,1,4,13,1,3,31,31,1,1},
14 {0,1,1,1,4,13,1,3,31,31,1,1},
15 {0,1,1,1,4,13,1,3,31,31,1,1}
16 };
17 int n,p[1000010],tot=0;
18 bool np[1000010];
19 int main(){
20     scanf("%d",&n);
21     for(int i=2;i<=n;i++)
22         if(!np[i]){
23             p[++tot]=i;np[i]=1;
24             if((long long)i*i<=n)
25                 for(int j=i*i;j<=n;j+=i)np[j]=1;
26         }
27     printf("%d %d\n",tot,(n<=16)?n-1:n);
28     if(n<=16)
29         for(int i=1;i<=tot;i++)printf("1\n");
30     else if(n>=26&&n<=34)
31         for(int i=1;i<=tot;i++)printf("%d\n",cheat[n-26][i]);
32     else{
33         int t=1,x=0,y=0;
34         while(p[t]*p[t]<n)t++;
35         for(int i=t;i<=tot;i++){
36             for(int j=i+1;p[i]+p[j]<n;j++)
37                 if(p[j]%p[i]==1){
38                     x=i;y=j;
39                     break;
40                 }
41             if(x||y)break;
42         }
43         for(int i=1;i<=tot;i++){
44             if(i==x)printf("%d\n",p[i]+2);
45             else if(i==y)printf("%d\n",p[i]+p[x]+1);
46             else printf("1\n");
47         }
48     }
49     return 0;
50 }
时间: 2024-08-25 13:51:49

[北京集训测试赛(三)]灯(Light)-奇怪乱搞数学题-素数的相关文章

[2016北京集训测试赛(一)]奇怪的树-[树链剖分]

Description Solution 对于操作1,不论选了哪个点为a,最后反转颜色的点集都只有两种类型(显然啦). 暴力解法:对每个操作3,从a向上直到根节点,每到一个节点记录(它父亲的黑点数减去自己的黑点数)*父亲节点的编号.另外,还要记录a子树内的黑点.. 这种O(n2)的做法肯定会爆,考虑优化.由于这是一棵静态树,考虑树链剖分. 需要记录一个数组re[x][0/1][0/1].第2维表示深度的奇偶,第3维表示点的颜色.例如:re[x][0][0]记录的是初始情况下以x为根的子树中深度为

【2016北京集训测试赛(八)】 crash的数列

Description 题解 题目说这是一个具有神奇特性的数列!这句话是非常有用的因为我们发现,如果套着这个数列的定义再从原数列引出一个新数列,它居然还是一样的...... 于是我们就想到了能不能用多点数列套着来加速转移呢? 但是发现好像太多数列套起来是可以烦死人的...... 我们就采用嵌套两次吧,记原数列为A,第一层嵌套为B,第二层嵌套为C. 我们其实可以发现一些规律,对于Ci,它对应了B中i的个数:对于Bi,它对应了A中i的个数. 稍加处理即可,我们一边计算一边模拟数列的运算,同时可以计算

[北京集训测试赛(五)/HDU5299]圆圈游戏(Circles game)-树上删边-圆的扫描线

Problem 遗产 题目大意 一个平面上n个圆,任两个圆只会相离或包含,给出每个圆位置与半径. alice&&bob轮流取圆,每取一个就可以取出这个圆以及被这个圆包含的圆. 没圆取的人输,alice先取,问谁有必胜策略. Solution Method #1 首先我们考虑一个暴力一点的写法: 先将圆半径从小到大排序,然后枚举两个圆,判断是否包含关系. 如果包含的话就将大圆连一条边到小圆. 很容易发现,这样执行完以后得到了一棵树. 我们接下来要做的事情就变成了: 每个人可以轮流从树上删除一

[2016北京集训测试赛17]crash的游戏-[组合数+斯特林数+拉格朗日插值]

Description Solution 核心思想是把组合数当成一个奇怪的多项式,然后拉格朗日插值..:哦对了,还要用到第二类斯特林数(就是把若干个球放到若干个盒子)的一个公式: $x^{n}=\sum _{i=0}^{n}C(n,i)*i!*S(i,x)$ 围观大佬博客(qaq公式太难打了) Code #include<iostream> #include<cstdio> #include<cstring> #include<cmath> using na

【2016北京集训测试赛(八)】直径

注意:时限更改为4s 题解 考虑最原始的直径求法:找到离根节点(或离其他任意一点)最远的节点far1,再从far1出发找到离far1最远的节点far2,far1至far2的距离即为直径. 题目中提到了将原树的子树复制成新子树这一操作,显然如果我们将子树真正复制出来是会爆炸的. 实际上我们可以将每棵新子树中,真正有用的节点提取出来,以简化每个子树的结构,再按照题目的要求连接各个新子树. 我们用虚树来重构每一棵子树.每棵子树的虚树的关键点应至少包含: 子树的根节点. 这棵子树内部的直径的两端节点.

【2016北京集训测试赛(七)】自动机 (思考题)

Time Limit: 1000 ms Memory Limit: 256 MB Description Solution 这是一道看起来令人毫无头绪的题,然而确实十分简单巧妙TAT. 题目要求所有点执行相同指令后都回到初始状态. 我们先来考虑只有两种状态的情况:初始状态$T_0$与另一个状态$T_x$. 这样,我们可以通过一个二元记忆化深搜,来得到一种方案A,使得$T_0$回到$T_0$,且$T_x$回到$T_0$.如果这个方案都不存在,那么此时无解. 现在我们知道,执行方案A后,$T_x$与

【2016北京集训测试赛】river

HINT 注意是全程不能经过两个相同的景点,并且一天的开始和结束不能用同样的交通方式. [吐槽] 嗯..看到这题的想法的话..先想到了每个点的度为2,然后就有点不知所措了 隐隐约约想到了网络流,但并没有继续往下想了... 听完学长的讲评之后(%xj)个人觉得建图还是很有意思的ovo [题解] 因为每个点到对面都有k种方式,那就想到每个点原来的点$x_0$拆成k个点$x_1$, $x_2$, $x_3$... $x_k$ 然后很自然地$x_0$和拆成的点之间要连边 容量的话,因为hint里面的限制

2016北京集训测试赛(十七)- 小结

先说一下总体的情况. 场上期望得分 50 + 40 + 30 = 120 , 最后得分 50 + 0 + 30 = 80 , 实际上自己能力所及能做到的 50 + 65 + 30 = 145 分. 第二题爆零是因为我开始写了一个做法, 后来发现这个做法是错的, 然后开始随机化, 调着调着突然发现只有一分钟了, 然后自己把之前调的改回来, 然后发现怎么全都输出 0 ??? Excuse me ?? 原本不用随机化的做法可以拿 40 分, 如果结合上暴力就有 65 了. 这几天打起比赛来还是暴露了许

【2016北京集训测试赛】azelso(unfinished)

[吐槽] 首先当然是要orzyww啦 以及orzyxq奇妙顺推很强qwq 嗯..怎么说呢虽然说之前零零散散做了一些概d的题目但是总感觉好像并没有弄得比较明白啊..(我的妈果然蒟蒻) 这题的话可以说是难得的一道搞得比较清楚的概d题目吧记录一下还是挺有意思的ovo 当然咯..显然考场上并没有推出来..嗯qwq [题解] 看到说要求期望的距离,然后总的长度又被分成了一段一段的(各个事件) 所以就有一个比较直接的想法:将每一段期望走的次数算出来然后再乘上每一段的距离,加起来就是答案啦 那么现在问题来了怎