love is hard to cut off,lifelong lovesickness

0%

小行星撞击防御实验——DART及个人思考

PART Ⅰ

什么是小行星撞击防御

行星防御(Planetary Defense)即应用一定的技术,以检测小行星或彗星撞击地球的可能性并发出警告,然后防止它们或减轻其可能的影响。

行星防御涉及寻找和跟踪有撞击地球危险的近地物体。

确定这些物体的特征,以确定其轨道轨迹、大小、形状、质量、组成、旋转动力学和其他参数,以便专家能够确定潜在撞击事件的严重性,警告其时间和潜在影响,并确定减轻影响的手段;以及规划和实施各种措施,以偏转或扰乱与地球发生撞击的物体,或减轻无法防止的撞击的影响。

在地球上可以采取的保护生命和财产的缓解措施包括疏散撞击区域和移动关键基础设施。

为什么要研究主动防御

在2019年年初,被发现的近地小行星的数量总共超过了19000颗。平均每周增加30个新发现。2016年10月13日达到15,000个里程碑,标志着自2013年以来已知的近地小行星数量增加了50%,当年8月发现的小行星达到10,000个。

96dda144ad3459828a886813746d37a6caef8451.webp

这些小行星里,有一些似乎对地球不那么“友好”,因为它们的轨道与地球轨道会有交叉的部分,这就意味着其有可能碰撞!

仅以2013年著名的“俄罗斯车里雅宾斯克小行星事件”为例,一颗直径仅15~17米的小行星冲进地球,就在一个人口稀少的城市造成了1491人伤亡。而对于一颗km级别的小行星,其相当于地球发生了一场全球核战争!

为了提前防止这一天的到来,也就应运而生了全球首次深空奔袭撞击小行星的实验——DART

DART目标

不同于日本的“隼鸟号”和美国之前的“冥王号”小行星采样,也不同于中国“嫦娥2号”和”罗塞塔“号等飞掠,这次美国的DART会直接撞上小行星Dimorphos,其瞬间粉身碎骨,把全部动量传递给小行星变轨(该防御任务不用直接摧毁小行星,当然也没有这个能力),其仅需稍稍改变小行星的运行轨道,使其”失之毫厘,谬以千里“,最大限度改变之后的运行轨迹。在正式防御小行星撞击时,其就可以错过于地球的撞击。而在深空中,一旦错过,也就是永别了!

选择孪生小行星Dimorphos和Didymos的原因是绝对安全,不会将其”推向“地球,且其大小适中,我们对其观测也很完备,可以做到万无一失!

35a85edf8db1cb1341191c34a1cd504593584bcc.webp

对于此次任务,正常情况下Dimorphos的轨道周期是11.9h,其直径仅160m,飞行环境纯粹,DART撞击可以将这个自身只能1000万倍的小行星速度改变0.4$ ms/s $,但已经能让它的轨道周期变化10min

DART’s Mission Objectives:

Demonstrate a kinetic impact with Dimorphos.
Change the binary orbital period of Dimorphos.
Use ground-based telescope observations to measure Dimorphos’ period change before and after impact.
Measure the effects of the impact and resulting ejecta on Dimorphos.

流程

预测轨道:近地天体研究中心(CNEOS)根据报告给小行星中心的位置计算近地天体的高精度轨道路径,CNEOS为新发现的小行星计算轨道,并对危险小行星相对于地球未来可能的位置进行长期分析,以确定和警告任何撞击危险

(DART并不需要携带科学仪器,事实上也没有时间进行测量,但是我们希望能够得到其撞击的图像以及撞击之后的资料,这就需要不同的观测手段)

远距离观测:有部署在10余个国家和地区的近20台地面望远镜参加了这次联合观测。与此同时,太空之中的哈勃太空望远镜和詹姆斯韦伯望远镜,小行星探测器Lucy,都把镜头对准了撞击地点。(但是远观并不能提供非常清晰的图像)

无标题-2.png

近距离观测:DART自身携带了一个小卫星LICIACube,其携带了两部高清相机,会在撞击完成后的2min45s飞抵现场,记录撞击后的情况。当然,最近距离的肯定是DART自己携带的高清相机了,其在撞击前最后2s拍下了距离小行星最近的也是最清晰的一张图片

6763579ae83de50601f03f5eb0ef9be1.gif

penultimate_dart_0401930049_43695_01_iof_imagedisplay-final.png

中国”保卫地球“任务

DART所测试的只是卫星防御计划的手段之一。另外,还有借助核爆、动能撞击、激光烧蚀、离子束牵引、引力拖拽、质量驱动等主动手段,破坏小行星的结构或者偏转小行星的轨道。

吴艳华透露,未来中国将组织编制近地小行星防御发展规划等任务,争取在”十四五“末期或者2025、2026年实施一次对某一颗有威胁的小行星进行抵近观测,实施就近撞击。

PART Ⅱ

对深空探测的意义

探寻生命

起源于探月工程,再到小天体采样任务,无一不是由人类对宇宙万物的好奇心驱使的。就像是黑夜中的独行者想要找到相互诉说的陪伴。嫦娥玉兔桂花树是古人浪漫的期盼向往,彗星上的有机物是现代人科学的曙光。

人们怀着尊重与自豪向宇宙发出无数次的呐喊,旅行者Ⅰ号携带的黄金唱片,真正得寄托了人们在真空无依得宇宙交流的渴望!唱片包含了55中人类语言,时任联合国秘书长库尔特和时任美国总统卡特的问候,90分钟的声乐集锦,包括地球自然界的各种声音以及27首世界名曲,其中包含了中国的古琴曲《高山流水》,还有115幅影像他,太阳系各行星的图片、人类生殖器图像及说明。

“这是一份来自一个遥远的小小世界的礼物,上面记载着我们的声音、我们的科学、我们的影像、我们的音乐、我们的思想和感情。我们正努力生活过我们的时代,进入你们的时代。” ——时任美国总统卡特

无标题-1.png

促进科技发展

虽说太空探索表面仅是促进航空航天技术的发展。但是,航空航天技术总是带领着科技进行变革的,每探索一个未曾涉足的领域,需要的新技术不是一两个突破就可以完成的,而是需要最前沿的科技互相协同并进。

太空探索迫使电子元件小型化,开启了电脑、网际网络、现代电子通讯设备、全球定位系统和微晶片等科技的革命之门。

另外想一想,科技进步是人类区别于世间其他物种的本质特征创造的,推动科技的发展也就是推动了历史车轮的滚滚向前。

提高人类生活质量

1970年当时身为NASA太空航行中心的科学副总监史都林格博士在写给赞比亚的Mary Jucunda修女的信中谈到了他对太空探索的重要性的理解

修女问道:”在目前地球上还有儿童由于饥饿面临死亡威胁的情况下,为什么还要花费数十亿美元进行飞向火星的航行?“我想这个问题一定不是个例,而是范例的代表。

史都林格博士认为首先,从现在开始暂停所有的太空项目,直到孩子们都吃上饭再说,这种方式并不会比探索星空对于消除饥荒的作用来得大。

显微镜的发明消除了世界上大部分地区肆虐的瘟疫和其他传染性疾病。同理,对于太空项目,可以涉及农业、畜牧业、渔业以及其他大规模生产活动,通过高科技手段,如灌溉管理、肥料的使用、天气预报、产量评估、程序化种植、农田优选农作物调查及收割计划来显著提高土地生产效率。通过人造地球卫星完成这些任务,带来的利益可比每年国会批准给航空航天项目的数十亿来得多

提高一代人的科学素养

无标题.png

这张图来自到达太阳系边缘的旅行者Ⅰ号距离地球60亿千米之外的地方回望地球时拍下的,最著名、也是最震撼的——”黯淡蓝点“。这足以改变我们面对他人和看待地球的方式,我们不会再仅局限于互相猜忌,而是更多地将有限的生命放任与大地长空、远山沧海

对中国深空探测的发展

了解人类深空探测历史的过程中,大部分视野是被美国占据了,这对于我来说是很大的触动,中国是对这一方面不感兴趣吗,还是……

我们抛开改革开放之前的深空探测历史,对于当代的发展,中国从成绩上来说确实是稳扎稳打,几乎没有失败,这在空天史上是极大的成功,但是正是由于这种头衔,或者可以说是国民的期待以及国情的压力,在新时代的发展中我们不容许失败,人民的热情才会更加高涨,使得中国在航空航天领域一再保守,对于一般团队出于兴趣的空天探索项目都是不会得到资助的,这于美国就相形见绌了,任何有创新、对人类探索有利的项目都可以参与竞争,得到立项支持。

另外,中国给人民的关于航空航天的消息着实太主观了。在网上进行搜索,并不能得到太多客观的对于中国航空航天的评价,甚至对于相关任务的信息都是报道式的主观概论,这对于国民客观了解航空航天工程发展都是不利的。相较于美国,NASA官网可以看到每个任务的大部分信息,让人们真正了解自己想要了解的客观一面。

中国未来深空探测的发展包括建立中国空间站、”保卫地球“小行星防御任务等。这些任务都需要大量的人才,我希望,越来越多的人才能够有施展自己才华,展示自己思想的空间,更多的包容总结,而不是更多程式化的主观限制,也希望能够让国民更多了解中国航空航天事业,让空天梦不属于少部分人,让它扎根进更多人的心中!

54fbb2fb43166d22767252cddf83fdfd9152d289.webp

参考文献

太空探索让人类获得了哪些实实在在的收益?

“保卫地球”行星防御计划将迎首次撞击测试,能不能行得通?

主动防御!人类航天器首次深空奔袭撞击小行星

Double Asteroid Redirection Test

DART in the News

The Differences in Grammar between AE & BE

Some situations around us

Today we focus on the rather insignificant differences in their grammar and speaking rules, here we have a lead in video clip to give u a little preview.

英式英语:

《神探夏洛特》《唐顿庄园》《IT狂人》(可放一些片段),当然还有《哈利波特》《国王的演讲》《傲慢与偏见》等

美式英语:

《破产姐妹》《生活大爆炸》等(一些片段)

The origin or history of the difference

  1. During the rather long colonial times, there was no significant differences between AE & BE. However, After the appearance of nationalist in the U.S, there came the ones who suggested to have their own concept of language, which gradually formed into a rather new type of traditional English.

  2. Due to the UK’s political system, the British is famous for minding their intonation and following strict grammar rules, for it is seen as a tool to show their good upbringing and graceful temperament. The Americans, on the other hand, speak in a rather easygoing way, thus form a not so complicated yet rather vigorous language system.

  3. Cultural and geological aspects, which are two of the main causes, are considered to be the two biggest influences. On account of the mass immigrants and cultural integration, AE was greatly reconstructed into its nowadays feature. BE remains, on the other hand, rather old-fashioned and traditional, while gradually adding and cutting out some of its European flavour.

    英语的发展经历了三个时期:古英语、中古英语、近代英语,在罗马人引进拉丁语、维京人促进英语的简化、诺曼公爵带入法语的影响下,随着英国的工业革命和殖民扩张,英语也随着大不列颠日不落帝国的士兵和商人开始散步到世界各地。

Appearance

\在北美大陆被殖民的很长一段时间里,美式英语和英式英语并没有什么显著的不同**。但在1776独立战争和1812第二次对英战争后,\民族主义势力抬头,促进了美国民族语言的确立和语言民族主义的出现**,当时,语言学家韦伯斯特等人\主张美国应该有自己独立的“国文”。**他首创“American English”一词。因此,\美式英语在一定意义上说话是从英式英语中分离出来的。**

Politics reasons

由于英国是一个君主立宪制国家,阶层等级影响深远,\因此英国人注重说话时的语气和腔调,以此来体现自己的身份和教养。**然而,美国是联邦制国家,一系列制度使美国主张平等、自由、人权,\因此美国人说话比较随和。**因此,这些政治原因也就逐渐对英式英语和美式英语的语法等方面产生了不小的影响

Cultural reasons

自1688年光荣革命以来,英国国内并未爆发过大规模的内战或者革命。普遍认为这与英国民族文化中的经验主义和渐变注意有关系。\这种文化传统使英式英语中的语法、词汇等变化相对保守**。而美国作为一个移民国家,\多民族的融合使得美式英语接纳了很多外来产物。**

Some difference between AE & BE

In general, there are no significant differences between the grammar system of AE & BE, compare with what we have seen in vocabulary and pronunciation. According to some linguists, there are no inventorial difference in the essence of English grammar, only with minor distributional differences, which is what we want to go through today.

总的说来,英美英语语法具有共同的体系,与语音和词汇相比,差异比较少,无明显规律可 循。语言学家认为,英美英语语法本质上不存在体系性差异(inventorial difference),只存在一些分布性差异(distributional difference)

Here we have the different usage of some verbs: get, have, seem, prepositions, articles, phrase like negative conjecture, modal verb, other tense, and subjunctive mood.

Verb:

Get:

AE frequently use the conjugation gotten to express motions such as to acquire, to obtain, to cause, to come,etc.

BE中无gotten形式,同时AE在表示to acquire, to obtain, to cause, to come, to succeed in doing, to come to have等意义时用gotten。

e.g.

(1)I’ve always gotten good service from them, let me give you their phone number and you can call them.(to acquire)

(2)she’s gotten a neurosis.(to come to have)(have gottem有“逐渐患上”的意思, have got只有“患上”的意思)

Have:

Apart for the common usage of have, which means owning sth in both AE & BE, BE widened its meaning in to a form of auxiliary verb, while AE use it solely as a notional verb.

BE中,have既是助动词,又是实义动词;AE中,只用作实义动词。

e.g.

(1)hasn’t she got a new green car?(BE)

(2)doesn’t she have a new green car?(AE)

​ 同时,BE用do you have的形式,表示经常;而AE用usually之类的词来表示。

e.g

(1)do they have enough to ear in Zambia?(BE)

(2)do thry usually have enough to eat in Zambia?(AE)

Like:

In BE, like is used more frequently to connect to do, while used to connect noun to refer to usual situations.

BE中,like接不定式多指具体情况,而接动名词多指通常情况;而AE中,更偏向于使用不定式。

e.g.

(1)I like swimming, but I don’t like to swim in such bad weather.(BE)

(2)that guy’s got a personality problem, he just likes to disrupt my life to make himself feel important.(AE)

Seem:

To refer to sth that looks alike, British people usually goes with phrase that is clearer, while AE came in with more prepositions.

BE中,如果添加名词,直接使用seem + n.;而AE中,需要使用seem to be + n.

e.g.

(1)he seems a clever boy.(BE)

(2)he seems to be a clever boy.(AE)

Must:

When denying sth, American English speaker frequently use the phrase Cannot/can’t, while British speaker express their veto by saying mustn’t/must not. With no significant differences in their extent of the negativity.

BE中,对于否定推测,用can’t or cannot;AE中,用must not

e.g.

(1)it can’t be true.(BE)

(2)it must not be true.(AE)

Need/dare:

In BE, the two words are used as auxiliary verb more often, while in AE, they can used as both auxiliary verb and Substantive verbs.

BE中,偏向于将其作为助动词;AE中,可用作助动词,也可用作实义动词

e.g.

(1)dare he say any word?(BE)

(2)does he dare to say any word?(AE)

Shall/will:

To express of demand sth that will happen in the future, BE often use shall while AE use will,

表示将来行为时,BE一般第一人称用shall,而AE倾向于用will。在过去将来时中,BE第一人称用should,而AE用would

e.g.

(1)we(or I) shall leave for Italy on Saturday.

(2)we(or I) will leave for Italy on Saturday.

Prep & Art:

To present the differences of prepositions and articles, we have two charts to help you understand.

wps1.jpg

wps2.jpg

虚拟语气:

In subjunctive mood, the major difference goes between whether the modal verb ‘should’ is neglected.

例如it is important/necessary/vital/essential + that从句的句型中,should是否省略

e.g.

(1)they suggested that all the people should set off right now.(BE)

(2)they suggested that all the people set off right now.(AE)

时态:

To present a motion in the near past, the British often use past perfect, while American speaker just talk in past simple.

在BE中,表示刚做完一个动作时,一般采用现在完成时,并于already,just,yet连用;而AE中,更常采用一般过去时表示。

e.g.

(1)i’ve just finished lunch.(BE)

(2)i just finished lunch.(AE)

The sense of singular and plural considering an aggregation.

An aggregation, such as a team, which is build up by multiple elements, has different definition about its nature. In BE, one might often say: Which team are losing when the speaker focus on the person and Which team is losing when the speaker focus on the elements. In AE, on the other hand, the question always goes as Which team is losing, regardless of the context.

口语:

Here, for the difference in spoken English, Aren’t/ain’t and OK/right must be the example.

Aren’t/ain’t:

反义疑问句中陈述部分是am时,附加疑问句BE习惯用aren’t来代替am not,而AE偏向于使用ain’t

e.g.

(1)i am older than you, aren’t i?(BE & AE)

(2)i am older than you, ain’t i?(AE)

其中ain’t不仅可以代替am not,还可以代替is not, has not, have not。

OK/right:

附加疑问句中,AE常用OK、right将附加疑问取代

e.g.

(1)we’ll have to go, right?

(2)let’s do it, OK?

电话用语this/that:

e.g.

(1)is that Tom?(BE)

(2)is this Tom?(AE)

What should we choose between AE & BE as a university student

First:\AE is used as the main language for more people.** Actually, in Britain, BE doesn’t refer to that it’s spoken by the whole of british people. There are amounts of dialects which are of big difference. However, Americans have more consensus in AE. Added that the influence of America there years, thus, AE is used more often than BE.

Second:As students, when it is time for us to look up some resources, \there are more in AE**.

Third:\we are able to change AE accent into BE easily.** Just like a southern man who decides to be expert in Mandarin Chinese, it is difficult for him because of the subconsciousness. But for AE users, it seems to be more easy.

In fact, there is no mandatory requirement of learning English. And it mainly depends on someone’s hobbies. Like BE? Maybe on account of its elegence. Like AE? Maybe by virtue of its simpleness and vividness.

First:\美式英语用的人多**。英式英语其实不是指整个英国讲的英语,而是特指伦敦那一小片地区的英语方言。英语有很多种不同的方言,彼此区别比较大。相反,美国人讲的美式英语很统一。再加上美国这些年相较于英国的影响力,将美式英语的人较英式英语更多。

Second:\美式英语的学习素材多**。就有声资料来说,市面上基本都是美式英语,并且美式英语的统一,使得其学起来目标明确。

Third:\美式英语可以换英式**。美式英语最大特色是卷舌音,发音较难,如果学会了美式英语,稍微练一下,可以从美式英语转换成英式英语。但相反,从英式转换成美式就较难。这就好比南方人学普通话,虽然知道是是翘舌音,但临时还是会反应不过来,需要专门训练了才会好一些

But:对于学什么英语并不是有强制要求,主要还是看自己的爱好,喜欢英式英语,可能是因为它的优雅高贵,喜欢美式英语,可能是因为它的简单生动。

References

朱留成.浅谈英式英语和美式英语的差异.[J].教学与研究,1993(15)

李颜伟.美式英语的形成与美国历史.[J].天津大学学报,2001(03)

张俊娟.关于英式英语和美式英语的差异性比较研究.[J].科技信息,2011(28)

Liston:https://zhuanlan.zhihu.com/p/422948107

英美英语动词用法的差异_刘佳芳

环球英语中英式英语和美式英语在语法上的比较_邵协

疫情之下自由的底线

生命安全

结论

生命安全是疫情防控的价值边界,任何侵害生命安全的“行为自由”都应该受到社会权力的约束。

如果在疫情没有得到有效控制之前盲目发展社会经济,这是对生命的不负责任。只有在生命安全得到优先保障的前提下才可以维护财产安全,才可以谈社会经济发展。某些西方国家奉行新自由主义,在疫情防空中将资本的自由流动与经济发展放到首位,去忽视了生命安全的保障,这是对自由意志基础的损害,实际上是资本逻辑导致的价值错位!

什么是行为自由和意志自由?怎么推出这个结论的?

​ 首先,自由可以分为这两者,行为自由和意志自由。简单来说,意志自由是基于人的精神自发性的自我决断,行为自由是贯彻“意志所欲”的自由。意志自由是目的,而行为自由是实现意志自由的工具性手段。

一方面,作为群居动物,社会会对行为进行一定的控制,社会控制行为的正当性基础在于维护社会秩序的稳定性,而社会始终是以个体构成,因此,社会控制行为要以维护“人”的本体存在位根本目的。

另一方面,意志自由是人之为人的根基,不能被强制。但意志自由的存在并不是无根的,它需要一定的物质基础,而人的生命安全是维护意志自由的首要现实条件。

进而,我们知道,无论在什么社会背景下,疫情也不例外,生命安全是谈自由的底线。

话语责任

在疫情防控中信息的获取、认知自由主要通过外界,所以,信息公开中应保护人的人格尊严,妥善保护相关人员的基本隐私,且不会扰乱社会秩序,影响他人意志自由。

结论

信息自由要以尊重他者与维护公共利益的责任为前提。

“疫情造谣者”散播的信息只会造成社会恐慌。过度的恐惧会损害人的理性能力,从而影响人的意志自由能力,所以应被惩戒。“疫情吹哨人”基于对他者的尊重和公共利益的责任及时传递信息,增强了公民预防病毒的自觉性与自主性能力,因此获得了言论自由资格。

结束语

以上就是我们小组关于这次课题的思考与讨论,有什么问题,欢迎大家和我们讨论与指正,希望都能在当今社会的万顷波中找到属于自己的自由

《周恩来旅日日记》$ ^ {[1]}$心得体会

写作背景:

周恩来以89.72分的优异成绩,在南开学校毕业,在《毕业同学录》中对他做出了“君性温和诚实,最富于感情,挚于友谊,凡朋友及公益事,无不尽力”;“君家贫,处境最艰,学费时不济,而独于万苦千难中多才多艺”,“善演说,能文章,工行书”,“毕业成绩仍属最优”的评价。

南开学校效仿英美教育体系,继续深造理应留学英美等国。校长张伯苓、校董严范孙也是劝说周恩来去英美的。可哀于家境艰难,以及留学日本有官费生的优惠条件,且日语夹带汉字,想来读写方便,且路费便宜,所以时年19岁的周恩来选择在亲友、老师、同学的资助下,于是年9月上旬由天津塔城海轮直抵日本东京。

行前,周恩来给送行的同学题了一首诗,也就是写在《学校日记》(《周恩来旅日日记》)衬页的那首《大江歌罢掉头东》,以壮此行。

大江歌罢掉头东,

邃密群科济世穷。

面壁十年图破壁,

不酬滔海亦英雄。

​ 中华民国七年一月

​ 游东周恩来自题于扶桑江户

​ 时年十九岁

​ 翔宇印

周恩来留学于东亚高等预备学校,全称是“日华同人共立东亚高等预备学校”,为曾在北京京师法政学堂任教的松本龟次郎先生1913年所创办,是当时日本最大的中国留学生教育机关,在籍学生经常在1000名左右,并有多年超过2000名左右。周恩来在东亚学校学习时的1918年,当时的留学生人数达到2085人,其中奉天178人,吉林69人,山东78人,江苏142人等。学习日文对于周恩来来说十分重要,不仅因为日文是周恩来在日本生活和求学必须具备的能力,是日本大专学校入学考试的重要科目,而且还因为他在南开学校所学的数学、物理、化学等科目都是英文教学的,如果不学习日文,对其他科目的考试也会带来很大的困难(对于曾经熟悉的学术名词都得重新记背)

在日本留学过程中,周恩来准备报考东京高等师范学校和东京第一高等学校(在文章中可以见到,考取这两所学校的过程也给了周恩来信念和思想上的重大转变)。而且如果考取其中的一所,就可以得到官费学习的待遇,这对于家境贫困的周恩来来说是十分具有诱惑力的。

修学 - 1:

“人要有志气。”我如今按着这句话,立个报恩的志气,做一番事业,以安他们的心,也不枉人生一世。

心得 - 1:

1918年新年第一天,周恩来用毛笔写下了在《学校日记》第一页上写下了第一天的日记,日记的上边框印有格言“少年立身即从今日起”,下边框印有诗句“闲话更端茶灶熟,新诗分韵地炉红”。

周恩来明确了写这本日记的目的,其一是“等着老年的时候想起幼时的光景,翻一翻这本日记,想着或者有点儿趣味。若是说留着事迹给人家看,这个我是万万不敢想的,亦不愿真够儿有这个事”,其二是周恩来感到自己已经19岁了,但想起从小儿到如今,认为自己一无所成、光阴白过,相比于自己在南开大学时非常喜欢的梁启超来说,自己真的无脸面对身边的人。

经历了7年的日本留学经历,周恩来意识到了时代之下自己应该有的责任,无愧于心,无愧于光阴,无愧于父老乡亲,志气之立,更待何时!

修学 - 2:

悟则为佛,迷则众生

佛门十戒:杀、盗、淫、两舌、恶口、妄言、绮语、嫉、恚、痴

三十不婚,可以不婚;四十不宦,可以不宦

与我善者为善人

心得 - 2:

其实从周恩来开篇的第一篇日记就可以看出,周恩来对于佛学的研究是很喜欢的,在定目标时,引用了“佛说报恩为无上”等句子,并且在之后的几天里,周恩来在修学一栏中不断收集佛学的语句,这对于他性格人格的塑造都起到了很深远的影响。

修学 - 3:

南北东西,鳏寡孤独

心得 - 3:

一月八日,冷风刺骨,早起进入东亚学校,就收到“八弟”的来信:“八姑父故去!”

周恩来身在海外,猛然间接到这个噩耗,“那时候心中不知是痛是悲,好像是已经没了知觉一般”,八叔父是周恩来生母、嗣母去世后的实际监护人。收到来信,想起了家中的种种,发现自己“鳏寡孤独全都占全了$ ^ {[2]} $”。再想起家中余事,家中一个要紧的男子也没有,后事如何了法?债务天天逼着,钱是没有,一家几口子饭是要吃的,但“当也当尽净了,卖也卖绝了,借是没处借,赊是没处赊”,还有八伯的病,何曾用一个钱去医治?这些事让周恩来在接下来的几天里生出了浓浓的思乡而不得归的愁情——“南望家乡归不得”!

修学 - 4:

炼铁石心肠,行其心之所安

心得 - 4:

老师接了周恩来的信件,知道了他日用不充足,便打算每月接济周恩来一些钱,并且得知老师要把事情告诉二伯。对于周恩来来说,心中愧意犹起,想起自己已经惊动的多少朋友,再向国内本就不安的家中打扰,怎敢?想着老师手头也不宽裕,周恩来问心哪能安呀!

因此,周恩来对于好好学习,考上有官费的学校的想法更加恳切!开始打算每天吃两顿饭,借着这个机会废寝忘食,并给下了“人定胜天”的自我激励。

修学 - 5:

人生三十无奇功,誓把区区七尺还天公

十年以后当思我,举国如狂欲语谁

心得 - 5:

周恩来实时关注日本的新闻,这让他心中对于政治方面的思考非常有感触。

他认为,现在这个时代情形下,做官的,有几个是真心为国的?在国内,确实爱国的人不少,大体分为两派:一派是服从革命;一派是赞成君主立宪。其虽意愿相同,但主意不同,并且没有合并的想法,留下的便只有互相攻击。周恩来反思认为“激烈派看着稳健派没有大出息,有奴隶性,极力排斥;稳健派看着激烈派暴跳乱骂,毫无建设思想,成事不足,败事有余,也持着反对的主意。”但他们自己真的预备好了吗?一个二个回国之后,还是毫无实力,能做的只有现出原形!

这时,周恩来想起了梁启超的《饮冰室文集》$ ^ {[3]}$中所说的“十年以后当思我,举国如狂欲语谁”,所以留学之事最大的就是需要建立真正立身的根本,去与这个恶劣的社会交战。

进而,周恩来定下了来这里求学的第一件事“炼得铁石心肠、刚硬志气,不为利动、不为势屈”

其实一想,我们所处的时代又何尝不是呢,小到竞争对手之间,很难去坦然接受对方的思想,但其实也没有立好自身的思想之基,知识相信于目前已知的狭隘范围内的了解,根基不稳,终会地动山摇;大到国家与国家之间,自己的文化输出成问题,便全盘遏制国外的文化输入,就连某些高身分的老师也会发出“过圣诞节就是崇洋媚外”的呼声,张贴的东西似乎就是想表达出自己的高修养,自己的意见绝对正确;某些企业也是“响应”国家政策,分不清全球票房跟国内票房,分不清美元与人民币。这种畸形的随从是国家真正想要的吗?我想不是,“取其精华,去其糟泊”互相借鉴学习才是和平时代该有的,诋毁、不分场合的诋毁、无底线的诋毁是可耻的、没有前途的。

修学 - 6:

人要是把精神放在是处,无处不可以求学问,又何必终日守着课本,叫做求学呢?

心得 - 6:

周恩来自从来到日本之后,觉得事事都可以用求学的眼光,看日本人的一举一动、一切的行事,以及一切的国情。所谓“知己知彼,百战百胜”,对于一般的留学生来说,看见和日本人要好就说汉奸,但英雄不计常人之议论,尽自己所能,在难得的留学生活中获得更多有用的东西。

另外,通览周恩来的日记,可以发现,在这一年当中,对于每天的气候,他都是用几乎不重复的四字词语进行描述,进而极大地扩展自己的词汇量,这是我们可以学习的地方,通过一件一般人都会将其当作小事的事,多花一点时间将其做精做细,就可以收获到远超这件小事该有属性的效果。

修学 - 7:

世界无穷愿无尽

心得 - 7:

经过对日美留学生当下情形的分析,周恩来得出了仁人志士的必要特征——大凡天下之人,有真正本事的,必定是能涵养,能虚心,看定一种事情,应该去做的,就拼命去做,不计利害;不应该做的,便躲着不出头,或是极力反对。

周恩来还对仁人志士的志向做了分析,他认为平常之人,不过是解决温饱问题足矣,但有大志向的人,便想去救国,尽力社会。这两者在不同信念层次的人心中地位相同,对于平常的人来说,吃没有尽,穿没有尽,因而对于国家社会之事,在仁人志士心中亦没有尽、亦没有足!即,真正的志士要不一而足,敢于探索。

但对于社会来说,某些派头的人,装着极其稳重的样子,专排斥激烈党,说他们不成事,自己却假公济私,虽说这两派人都是迎合社会,但稳重党,社会上不知道他是假的。周恩来分析时局,给出断语——这样子的人,已经无处不有了。因此,在这种背道势力一天比一天多的时代,“除旧迎新”的力量也必须一天比一天多!

修学 - 8:

第一,想要想比现在还新的思想;

第二,做要做比现在最新的事情;

第三,学要学离现在最近的学问。

思想要自由,做事要实在,学问要真切。

心得 - 8:

二月十一日,农历新年伊始,周恩来想起了家乡的俗语:“大年初一不高兴,一年都晦气”,但满腹的愁情,叫周恩来如何高兴。三思之后,决定抛却以往的不高兴的事儿,一方面遵循家规,另一方面就是展望未来,定下目标!

这一天,周恩来的日记上写着“阴云满天”,但他的志向犹如霹雳斩断愁情,立下了“有如三宝”。自记日记至此两个半月,周恩来的人生感悟大体清晰,他冷静思考周围群体的素质,时代的波动,以找准了自己的方位。

修学 - 9:

宗教家常说人要信宗教就是“更生”、“重生”。我觉

得我这回大领悟,将从前的全弃去了,另辟“新思想”,求“新学问”,

做“新事情”,实在是同“重生”、“更生”一样子了

心得 - 9:

之前在国内的时候,周恩来总忙着学校内的事情,对于1915年创办的《新青年》杂志,并没有什么关注。之后后来,周恩来从天津准备动身的时候,运弟给了他一本《新青年》三卷四号,及到了东京,又从季冲处看见了《新青年》三卷全份,心里越发高兴。

周恩来这意识到了,自己之前所“思”、所“学”、所“行”实在是无一可取,那种茅塞顿开、醍醐灌顶的感觉溢出纸外,就连周恩来这一段时间的“修学”部分大都是关于当代科学和政治领域的先进名词。

周恩来在“风雪残留犹未尽,一轮红日已东升”旁边,画了一个圆圈,表达了自己的喜悦心情。屋外是“风雪交加”“北风凛冽”,他心中的“红日”就是《新青年》提倡之各种主义!“我愿意自今日后为我的‘思想’、‘学问’、‘事业’”去开一个新纪元才好呢!”

修学 - 10:

毋自欺,精一,寡欲;坚忍精进,预备工夫

心得 - 10:

“落第”对于这一年的周恩来来说,似乎早已是司空见惯的事情了,就连还没出榜时,就已经不抱希望了,“心定矣”。

对于一同报考东京高等师范学校的好友犹豫是否退学考取东京第一高等学校,然后再上帝国大学,周恩来劝导他说:“不能只顾一时得失,动摇多年的志愿,而应考虑国家的需要和个人在哪方面可能发挥更大作用,以决定取舍。”这也给落第的周恩来坚定“铁杵磨成绣花针”信念的信心,惟精惟一,允执厥中!

修学 - 11:

日本何尝是褴褛呢,想怕中国不免有些没出息的样子了。举一反三,我想起日本的国民无怪他瞧不起中国人,他的知识实在是从小儿就练出的。中国人一知半解,那能够讲到开通呢。

心得 - 11:

周恩来在山兄的建议下来到了日比谷公园,在这里,周恩来深切得感受到了中日在20世纪初新青年表现出的巨大差异。无论男女,日本孩子做什么事情,总是含有点教育兴味,在周恩来以为两个女孩子在玩泥巴时,移近才发现实在种草。中国家长、教师一提到日本,便是“东洋褴褛之邦”,但从新一代看来,中国似乎才是褴褛之邦。拯救现状的方法只有一个,那就是翻新中国的思想。

谈到当下,在孩子尚小时,家长们教育孩子的总是溺爱,照顾,仅此而已,而在日本,以及当代很多西方国家,寓教于乐,父母亲自带孩子们感受大自然的神奇,已不足为奇(我印象很深的一次是刷视频的时候,看到了一个国外的孩子摔倒,一声不吭地爬起来,一脸愤怒地锤击地面,打开评论区,尽是“这要是放在中国,家长身上都要掉层皮,孩子泪都得流干了”,真是这样吗?真是这样)。 在当前双减政策下,中国意识到了应试教育的弊端,家长在教育过程中的缺失,想要孩子们真正的激发出创造力,这是好的引导,但在当前的人们固化思想下,这种转变很难得短时间内为广大家长们所接受,就自己来说,虽然我知道这种开发式探索式的教育肯定是好的,但对于我的弟弟,看到他们一、二年级没有考试,没有排名,真的很担心,不知道他们学的怎么样,对于广大的家长朋友们来说更是这样,只要有机会,就会逮着老师问,自己家的孩子在班上成绩如何什么的,真是矛盾,很是矛盾!

修学 - 12:

霹雳一声中日约,亡奴何必更贪生

一国之强弱,视人民之德行

哲学的思想,科学的能力

心得 - 12:

自五月二日起,由于中日新约行将成立,此间留学生有全体归国议论,甚至有“破指血书者”,在“大中华民国救国团”的巨大反响下,东京私立十一校商榷对待学生全体休课之事,世故圆滑,用词违心——“吾等诸君之有碍学业,留学之目的中途挫折,不忍旁观,拟速向政府当局交涉,期解诸君忧虑,安诸君之意,而精励诸君之学业也”。而中国留学生爱国热诚之深,快速决断各省代表团归国日期。

同时,周恩来于五月十九日加入新中会,发出了“我们中国所以如此衰弱的缘故,全是因为不能图新,又不能保旧”的入会意见,所以周恩来看见这个“新”字,赶到异常痛快!总结时,周恩来说出了两句要紧的话——“哲学的思想,科学的能力”,即在周恩来看来,中华民族想要存活发展,就必须不断学习,吸收外来文化,文化不进则退!

现在的中国强起来了,但我认为,我们还没有完全做到周恩来所提到的“主动的观察力”、“被动的熏染力”,我们也只是在习主席上台之后才逐渐提升了文化自信,这一切都是一个循序渐进的过程。但总会有一些忧虑在社会之间荡漾,“摆烂”一词近年成为热词,这和上世纪英国出现的尼特族、日本出现的蛰居族很相像,这也就让社会产生了很多关于这一代是否会毁掉之类的讨论,但其实由我看来,这些网民或者所谓的专家都只是浮于表面的即兴谈词,对于青年人之间常挂在嘴边的摆烂,第一点,它或是调侃,或是自嘲,人们之间的目的其实大部分都是一种自我解压的方式,给自己一些正当的空间进行调节;第二点,当它在人与人之间成为一种交流的工具时,当它成为互联网居民互相发的表情包时,当它逐渐成为一个“梗”时,摆烂这个词也就给了青年们一种广义的集体归属感,当他们在劳累过后,与网友说起摆烂,他得到的是一种解脱,一种解闷,投身于一个集体中,在这个集体间,人们都互相体谅,互相打趣,此不失为一好处!

修学 - 13:

那些拥有最好的家庭、社会、法律、政府,最先进的科学和艺术,最纯洁的信仰,最美好的道德和最优秀的智慧的民族,才是最有份量的民族

滔滔者天下皆是耶

心得 - 13:

在连续多天的紧密考试之后,周恩来还是意识到了自己成绩应该没望,发出“我们必须鼓足勇气,去面对那些小困难。否则这些小困难就会扩大成大困难”的感想,结合近期留学生归国热潮,中日矛盾,周恩来在低沉的处境中找到了有份量的人民,有份量的民族该有的东西——贯穿在他漫长一生中的自我牺牲精神,这种精神使他更为光荣,出类拔萃。失败的沼泽不会困住冷静的人,在接下来的日子里,周恩来对自己每日鞭策,“还救什么国呢!爱什么家呢!”“矧吾

双亲已没,娱乐之何求?过渡时期,滔滔者天下皆是耶”,悟出,珍惜时间才是救亡图存的充要出路

终:

回国没多久,又得再次去往东京求学,别生父,别慧弟,只身羁旅,孤单单心之极伤,两个月未曾提笔!

从八月二十七日起,直至十月二十五日,周恩来未尝提笔一记。之后的每日修学中,“坐卧不安”“黯然销魂”等记录了周恩来的心理状态,可见其内心家乡与国家种种矛盾交织,思想的进一步羽化冉冉泱漭!

注释:

[1] 这是一本泛黄的《学校日记》,上面印有“学校日记,中华民国七年阴历岁次戊午,日历依中央观象台历书,上海商务印书馆制”的字样;扉页上“周恩来”的署名,因保存者为了防备反动当局搜查而暴露,只保留“周”字,“恩来”二字及红色印章均已被挖掉或涂抹不清,但页下保有书“翔宇”二字的用印,两封印章均为篆书,红印泥用印。

[2] 老大四伯父在东北,膝下无儿女,是“独”;老二是周恩来生父,死了妻子,是“鳏”;现在八伯父去世,八伯母成了“寡”;周恩来过继给老四,是他的十一叔,嗣父母双亡,他成了“孤”。

[3]梁任公即梁启超,《饮冰室文集》收录了他的诸多著名文章,如《变法通议》《新民说》《新民议》《爱国论》《少年中国说》《中国不亡论》《意大利建国三杰传》《社会主义论序》《自由书》《敬业与乐业》等等。周恩来在南开读书时,就特别喜欢读梁启超的书和文章,还曾为梁启超的讲演作过笔录,发表在校刊《校风》上。

一些摘抄

图片1.png

图片2.png

图片3.png

图片4.png

图片5.png

图片6.png

图片7.png

图片8.png

图片9.png

图片10.png

图片11.png

图片12.png

图片13.png

图片14.png

图片15.png

卖情怀?行走在舆论风口浪尖的中国爱国与科幻题材电影

杨佳宇轩
(士嘉书院 227513 22375080)

正文

偶然间看到一句评论“凭什么爱国电影给差评就要被喷?给差评就是不爱国吗?这种商业电影就是在卖爱国情怀,在挣钱,在打着爱国旗号卖情怀不知道是悲是喜。”,卖情怀?虽然不敢肯定,但扪心自问,我曾经也厌倦了国产爱国电影,为什么每逢节假日,热榜上总会有几部爱国题材电影?这让我想要去想一想卖情怀的帽子是否能扣在爱国题材电影上。

首先,爱国题材电影内容是什么?这个应该都清楚,以与爱国精神相挂钩的历史事件及人物为主题,反映和传播中国精神,俗称红色题材电影。由此,我们知道爱国题材电影的作用是提高国民的爱国意识,增强国民的精神归属感。

那么,如此正统的,意义上与利益无处挂钩的电影为什么会出现文章开头提到的愤慨评论呢?

第一,我认为,无论是给出差评者还是批判者,本质上都是爱国的,他们只是站的角度不同,在自身的价值观中,赋予给爱国电影需要付出的责任的权重不同。作为差评者,他们点出的差评,不是点在爱国精神或者历史人物上的,他们对电影的批判是中肯的、客观的、倾注自身思考的、建立在自身对电影本身好坏的评价上的,他们有自身的“言论自由”,“点评自由”,他们点出了他们认为不正确的宣扬爱国情怀的方式,所以,他们是知道应该怎么爱国的。同样,对于批判者,他们同样爱国,也许有人会说他们这是明显的“畸形、扭曲式爱国”,但我认为他们只是把自身更大程度上地融入到了电影所反映地历史事件中,他们看待这部电影,就是在看待曾经艰苦但却峥嵘的历史岁月。所以,这两者会有争执,只是因为他们没有换位思考,没有想要走出自己的思想固笼。

第二,这与互联网信息的碎片化、以及电影官方的带节奏有关系。透过一面冰冷的屏幕,你可以看到彼人在说这段话时的语气、表情、动作、心理活动吗?不能。甚之,观看者会强加自身的情绪以及片面理解,以至于误解。同时,在短视频平台日益高涨的流量下,电影宣传的官方账号日益增多,截取电影片段进行过度解读,想要将历史情怀强加到流量和票房这种商业行为上来,以此来将观众(电影观众以及短视频观众)的爱国情怀与票房、点评相挂钩。这合理吗?对于一些“爱国热情过激”的人民群众来说,这不是唤醒爱国热情,这是扭曲爱国情怀的涉及范围!

那么,爱国题材电影的的社会价值应该是怎样的呢?首先,要谈这个价值,我们默认讨论的是剔除掉单纯“卖情怀”的电影。柏拉图在《理想国》中提到了一个概念——每个人天生都有自己独特的特质,而后天的教育就是要最大程度得按照他们得天性,将他们培养称为不同的职业者,比如农民、匠人、战士或者哲学家,然后将他们输送到社会里相应的岗位以实现每个人社会价值的最大化。由此,我们可以得到爱国电影社会价值最重要的一点结论——爱国主义电影是唤醒中国人骨子里流淌的爱国情怀,一次又一次不停地告示着活在这个看似和平年代的人们,要心存善意、心念感恩、及对于先辈的尊重和对历史的铭记。

图片1.png

有了理论基础之后,我们看一下国内票房榜单,可以看到进入中国影史前10的影片中有4部为主旋律电影,其上映时间全部都是近5年。所以不由得想一个问题,为什么红色电影在近些年如此火热?我认为,这可以部分视作中国电影成熟的标志。每个国家的电影都有自己的政治正确,这种政治正确在电影中以要素或者话语形式存在,同时作为一种价值内核内嵌到电影之中。在中国,爱国主义精神是当下中国政治正确最重要的内容之一。成熟的电影市场往往意味着本国的主流电影能够反映本国的社会思潮和价值偏好。例如,《美国狙击手》《萨利机长》是美国的主旋律电影,同样《复仇者联盟》《美国队长》等也体现了美国的价值观。由此观之,可得爱国主义电影叫好又卖座,是主旋律电影主流化的表现,是中国社会主义核心价值观深入人心的表现。

最后,返回这件“差评”事件本身,他们对宣扬爱国题材社会价值有什么启示吗?第一,爱国应该是趋势,国家是应该推动的,是正能量的,是值得去呼吁所有中国人拥有的,其根植于每个人内心的向心力,不是一句卖情怀可以涵盖的,更不是一句是否给差评所能去讨论的。第二,既然市场上存在,并且在高票房市场上不乏用情怀换取利益的行为,我们仍然可以去观看,可以对电影本身进行批判,这一切都是自由的,但一定要注意个人言论所带来的思想激荡是否是对社会发展趋势有害的,另外,不要把个人对于电影的情绪强加于电影背后的历史事件和人物,我认为,这是讨论这个话题的底线。

想到这里,我不禁联想到国内其他类型的电影行业发展趋势,其中令我感概最深的便是近期舆论讨论激烈的以《明日战记》为代表的国产科幻片。

在暑期的重磅大片中,《人生大事》17.12亿,《神探大战》7.12亿,《独行月球》31.02亿,而《明日战记》6.77亿,这个票房乍一看还不错,但是相对于它的成本4.5亿港币,很明显它是最大的输家。

由于上映之前的大量高品质宣传与如今最大输家的参差,争议愈演愈烈,官方便在上映之前的“古天乐的中国科幻梦想”基础上,进行各式各样的宣传,但是,说宣传似乎不太合理,更准确的应该是说“饭圈行为”——首先是卖情怀,从用古天乐的名气吸粉,让古天乐在各大平台进行直播宣传,再到做慈善带来路人缘,然后是古天乐对于中国科幻的支持和所谓的梦想,最后便只剩“卖惨”(古天乐每天宣传很累,但面对观众依旧百分百打起精神,就算在私底下默默擦着眼泪,仍然坚持梦想)。

这让我不由得想,《明日战记》值得更高的票房吗?甚之,它值得现在的票房吗?首先肯定的是,也是唯一肯定的是,这部电影的特效在国内很好。所谓中国首个机甲科幻电影,第一个问题就是剧情太差,这也是观众反应最频繁的一点(这部电影和92年日本动漫《宇宙骑士1》设定以及剧情几乎重叠)。第二点就是导演吴炫辉在预告时宣传的“故事背景设定在一个现实的世界,我们必须从一张白纸开始,创造出一个新的世界,从外星怪物到演员穿的铠甲到装甲车辆等等,我们要创造出令人信服的一切”。事实真的如此吗?无论是古天乐和导演二人对机甲概念的理解,还是场景里和《异形》《哥斯拉》几乎相同的怪物设计,现在回头看这句话感觉吹嘘的成分居多,务实的成分较少。

图片2.png

第三点,《明日战记》想融入的元素太多了,宏大叙事爱国情怀它真的具备了吗,从电影中看,地球防卫队,竟然没有组织标志,甚至没有国家的国旗,相较于同期的喜剧电影《独行月球》,在淡化国家概念时也不忘在救援团队成员手臂上贴醒目的中国国旗。

图片3.png

科幻电影难道必须通过这些卖观众对于科幻以及对个人的情怀的手段达到卖点吗?这个答案显然是“不”。先看国外,漫威影业是卖情怀吗?他能够将年轻人喜欢的东西转换成他们激动的心情,并历久弥新,沉淀在脑海里,久久回味,仍然激情澎湃,你见过《复仇者联盟4》全球首映的现场!那种激情是无与伦比、史无前例的。再看国内,像《流浪地球》这类被视作中国科幻崛起里程碑的电影它能够将想要表达的、观众们希望看到的在电影中无一遗漏地表现出来,那就是一部成功的科幻电影。

所以我通过近期行走在舆论风口浪尖的爱国题材电影和科幻电影得出一个结论:电影情怀可以承载回忆、成为回忆,但不能成为为盈利的卖点,无论是哪种题材的电影!

参考资料:

关于最近火热的所谓电影卖爱国情怀论点的一些想法与观点

浅谈爱国主义电影的社会价值

明日战记票房惨淡古天乐落泪面对观众依旧苦笑

卖惨,炒情怀,还攻击同期国产电影,古天乐新片比《上海堡垒》还要恶劣

为什么近几年票房好的中国电影多为爱国主题?

下自成蹊三十载,爆轰闪光铸辉煌$ ^ {[3]} $

杨佳宇轩
(士嘉书院 227513 22375080)

身为一叶无轻重,愿将一生献宏谋

图片4.png

你想到了什么?

“面对这样庞大的题目,我不能有另一个选择。一个人的名字,早晚要消失,能把微薄力量融入祖国强盛之中,便足感欣慰。”当这句话填满眼眶时,你,想到了什么?

古人将名留青史作为活过的唯一证据,确实,没有人可以万古长青,但可以有人做到灵魂亘古延绵。然而,于敏先生在面对祖国召唤时,毅然投身到我国核武器研制事业!“对于敏个人而言,这是很大的损失”他的一位老同事如是说到。哪些人能有如此的信念?青年马克思在《青年选择职业时的考虑》$ ^{[4]} $中说到:“如果我们选择了最能为人类而工作的职业,那么,重担就不能把我们压倒。那时我们所享受的就就不是可怜的、有限的、自私的乐趣,我们的幸福将属于千万人。面对我们的骨灰,高尚的人也会洒热泪!”那么,于敏先生甘愿隐姓埋名的精神是否来源于他对祖国、对人类的无私情怀呢,让我们走近于敏先生,领略老先生“身为一叶无轻重,愿将一生献宏谋”的一生。

少怀其志,敢蹑其路

于老先生出生于1926年8月16日。于老先生的青少年时代是在抗日战争时期的沦陷区度过的,童年亡国奴的屈辱生活给他留下惨痛的记忆,一颗种子似乎蓄势待发。

1944年,于敏考进了北大工学院机电系。但上学后于敏发现,这里的工学院只是把知识告诉学生会用就行了,根本不告诉学生根源。而他却偏偏喜欢沉浸在“纯粹”的理论之中,高深的物理学像一块巨大的磁石吸引着他。1946年于敏先生转到理学院物理系,并将自己的专业方向定为理论物理。他在理论物理方面的天赋很快展现出来,并以惊人的记忆力和领悟力赢得教授们的欣赏,当然,也更加坚定了于老先生攻克物理理论研究的决心。1949年于敏本科毕业。不久,他被慧眼识才的钱三强、彭桓武调到中科院近代物理研究所。这个所1950年才成立,由钱三强任所长,王淦昌和彭桓武任副所长。

1961年1月的一天,即将准备出国留学的于敏先生奉命来到钱三强的办公室。一见到于敏,钱三强就直截了当地说:“经所里研究,请报上级批准,决定让你参加热核武器原理的预先研究,你看怎样”。时间仿佛在此刻驻足停留,心跳声在房间里犹如闷声巨响,于敏先生没有沉默,他说出了那句话——“面对这样庞大的题目,我不能有另一个选择……能把微薄力量融入祖国强盛之中,便足感欣慰。”

郭永怀在和于敏先生见面时说到:“从明天起,谁也不知道你干什么,包括你的家人,他们也许会怀疑,因为你犯了错误被调离了岗位,当一个什么话都不能说的哑巴……”“你来一碗,我也得来一碗;你有,我也得有,人和人之间,国家和国家之间,都一样……什么是底气,我们造的就是底气!”

虽千万难吾往矣

当时国内很少有人熟悉原子能理论,一切似乎都是从零开始。在研制核武器的权威物理 学家中,于敏是唯一没有留过学的人。不仅人员紧缺,科研小组的粮食供应也只能维持在“有吃”的层面,于敏先生有胃病,曾经因为没有东西填肚子而疼不能忍。唯一能支持他们坚持下去的是他们对理论物理的热情,于敏先生的一句口头禅便是“理论没问题”。

从一张白纸开始,科学家们面临的第一个挑战便是对于测量氚氚反应截面实验选择相信美国期刊的参数还是基于中国的理论,一句“不会错,理论经得起推敲,不能盲目相信美国人”定下了理论物理研究的方向,避免了数亿人民币的损失和三年时间的浪费。

设计了模型后,困难如期而至,从原子弹到氢弹,按照突破原理实验的时间比较,美国人用了七年零三个月,英国四年零三个月,法国八年零六个月,前苏联四年零三个月。主要一个原因就在于计算的繁复。而我们的设备由技术的限制,全国仅有一台每秒万次的电子管计算机,并且95%的时间分配都交给了原子弹的计算,5%的时间分配基本都是在半夜12点之后。“穷人有穷方法”,于敏先生领导小组人员,人手一把计算尺,废寝忘食地计算,倒下的不是个例。

同事问于敏:“我们如此研究,就是为了搞清楚氢弹怎么才能爆炸,等到研究成功了,又永远不希望它爆炸,那我们研究它的目的是什么?”于敏先生瞪大眼睛,双手不禁跟着话语动了起来:“如果我们没有氢弹,别的国家就会肆无忌惮,别的国家的核武器就可以随时随地扔到我们的国土上,这叫核平衡。我们制造核武器,是为了让别的国家的核武器不会爆炸……咱们不发动战争,但要有面对战争的能力和准备,和平求不来,有实力,才能不挨打!咱不欺负别人,也不让别人欺负咱们!”

为了调动大家的积极性,在那个食物短缺的年代,于敏先生拿出自家攒的鸡蛋,给每个有理论突破的同志鸡蛋奖励。

期间,于敏先生曾三次与死神擦肩而过。1969年初,因奔波于北京和大西南之间,也由于沉重的精神压力和过度的劳累,他的胃病日益加重。我国正在准备首次地下核试验和大型空爆热试验,于敏先生参加了这两次试验。当时他身体虚弱,走路都很困难,上台阶要用手帮着抬腿才能慢慢地上去。热试验前,当于敏先生被同事们拉着到小山冈上看火球时,已是头冒冷汗,脸色苍白,气喘吁吁。大家见他这样,赶紧让他就地躺下,给他喂水。过了很长时间,在同事们的看护下,他才慢慢地恢复过来。由于操劳过度和心力交疼,于敏在工作现场几至休克。直到1971年10月,考虑到于敏先生的贡献和身体状况,才特许已转移到西南山区备战的妻子孙玉芹回京照顾。一天深夜,于敏先生感到身体很难受,就喊醒了妻子。妻子见他气喘,赶紧扶他起来。不料于敏突然休克过去,经医生抢救方转危为安。后来许多人想起来都后怕,如果那晚孙玉芹不在身边,也许他后来的一切就都不存在了。出院后,于敏顾不上身体未完全康复,又奔赴祖国西北。由于连年都处在极度疲劳之中,1973年于敏在返回北京的列车上开始便血,回到北京后被立即送进医院检查。在急诊室输液时,于敏先生又一次休克在病床上。

四年中,是科研人员的舍己为公、坚定意志,才使得一篇又一篇的论文交到了钱三强的手里,一个又一个未知的领域被攻克。于敏团队提出研究成果报告69篇,对氢弹的许多基本现象和规律有了更为深刻的认识。

漫漶相连,晨光泱漭

1964年10月16日,我国第一颗原子弹爆炸成功,周恩来总理代表党中央和国务院下达命令:把氢弹理论研究放首位。同年,于敏先生带领一支小分队赶往上海华东计算机研究所,抓紧时间计算了一批模型,终于发现了热核材料自持燃烧的关键,解决了氢弹原理方案的重要课题,难掩愉悦之情的于敏先生说到:“我们到底牵住了‘牛鼻子’!”。

当即,于敏先生给远在北京的邓稼先打了一个耐人寻味的电话,但由于保密,只能通过他们才能听懂的隐语:“我们几个人去打了一次猎……打上了一只松鼠。”邓稼先听出是好消息:“你们美美地吃了一餐野味?”“不,现在还不能把它煮熟……要留做标本……但我们有新奇的发现,它身体结构特别,需要做进一步的解剖研究,可是……我们人手不够”“好!我立即赶到你那里去”。

年底,于敏先生开始从事核武器理论研究,在氢弹原理研究中提出了从原理到构型的基本完整的设想,在最后算出结果的那一刻,他没有激动,而是让研究人员再算一次,再算一次,再算一次……终于,在他宣布成功的那一刻,身体不能在支撑他,累倒了。

图片5.png

1967年6月17日8时整,空军飞行员徐克江驾驶载有氢弹的飞机进入罗布泊空投区。随着指挥员“五,四,三,两,幺,起爆!”的指令,机舱随即打开,氢弹携着降落伞从空中急速落下。弹体降到距地面两十几白多米的高度时,只听一声巨响,碧监的大空随即翻腾起熊熊烈火,传来滚滚的雷鸣声……红色烟尘向空中急剧翻卷,愈来愈大,火球也愈来愈红。火球上方渐渐形成了草帽状云雾,与地面卷起的尘柱形成了巨大的蘑菇云。强烈的光辐射,将距爆心投影点四百米处的钢板铸件烧化,水泥构件的表面被烙;布放在八公里以内的狗、十公里以内的兔子,当场死亡一半;七百米处的轻型坦克被完全破坏,车内动物全部炭化;冲击波把距爆心投影点近三公里、重约五十四吨的火车吹出十八米,近四公里处的半地下仓库被揭去半截,十四公里处的砖房被吹散。科技人员把爆炸当量的数据送上来了――三百三十万吨!

黼蔀黻纪,向阳而生

数十年默默无闻,于敏却怡然自得。他喜欢诸葛亮,喜欢诸葛亮的“鞠躬尽瘁,死而后已”,更是将诸葛亮的“淡泊以明志,宁静以致远”奉为圭桌。这个内向又安静的科学家,对“宁静”有着自己的理解:“所谓宁静,对一个科学家而言,就是不为物欲所惑,不为权势所屈,不为利害所移,始终保持严格的科学精神。

这份“宁静”,让于敏的身影显得更伟岸。当国家授予他“两弹一星”功勋奖章时,于敏说这是集体的功劳。当人们把“氢弹之父”的称号送给他时,他直言这种称呼不科学:“核武器的研制是集科学、技术、工程于一体的大科学系统,需要多种学科、多方面的力量才能取得现在的成绩,我只是起到了一定的作用,氢弹又不能有好几个‘父亲’。”

完成氢弹之后,于敏先生决心扎根核事业。意识到惯性约束聚变在国防和能源上的重要意义,他立即组织指导了中国核理论研究的开展。1986年初,邓稼先和于敏对世界核武器科学技术发展趋势做了深刻分析,向中央提出加速核试验的建议,加速发展惯性约束聚变研究,并将其列入中国高技术发展计划,使中国的惯性聚变研究进入了新的阶段。

面对这样庞大的题目,我想,于老先生并不是没有其他选择,而是他遵从了内心的神往,毅然选择了核事业。他的名字将刻在神州大地上,融入祖国的强盛中,熠熠生辉!

参考文献

[1]电视剧《功勋》
[2]氢弹功臣于敏小传 人民网[引用日期2014-08-15]

[3]于敏:身为一叶无轻重 愿将一生献宏谋

[4]于敏,贺流体物理研究所成立五十一周年暨独立建所四十周年题词

[5]《青年在选择职业时的考虑》马克思

星图研究——子图同构Ullmann算法

背景

​ 为了在全天星图中找到想要识别的星体,如果仅凭肉眼,是很难实现的,那么我们就需要寻求计算机的帮助,设计高效的算法来进行精准快速的匹配。也就应运而生了两种主要的算法

目前图同构常用算法大概有:

Ullmann算法、VF算法、VF2算法、vf2x算法

这里我们主要研究子图同构算法中的Ullmann算法!

340e4eb8b43ea8dbd3a60081189c2cf7deb21640.webp

问题性质

分类

无标题-2.png

P类问题(Polynomial Problem)

P类问题是指一类能够用确定性算法在多项式时间内求解的判定问题

(对于某些非正式的定义中,我们可以把那些在多项式时间内求解的问题也称为P类问题)

for example:矩阵乘法就是一个P类问题,其时间复杂度为$ \mathcal{O}(n ^ 3) $

NP类问题(Non-deterministic Polynomial Problem)

NP类问题分为猜测和验证过程。NP问题是指不能再多项式时间内解决或者不确定能不能在多项式时间内解决,但可以在多项式时间内验证一个解的问题。

其也可以理解为,可在多项式时间内猜出一个解的问题。比如,在某个题中,找一个解很难,但验证一个解很容易。

for example:商旅性问题(TSP,Traveling Salesman Problem)的判定就是一个NP类问题,其时间复杂度$ \mathcal{O}(n) $

NP-complete问题(NP-complete problem)

我们判定一个问题D是NP-complete问题的条件:

(1)D属于NP类问题

(2)NP中的任何问题都可以在多项式时间内转化为D

证明方法:必须找到一个已知的NPC问题可以转化为当前问题D,则当前问题D为NPC问题(也就相当于一种数学归纳法)

for example:集团决策问题就是一个NP-complete问题。

NP-hard问题(NP-hard problem)

一个问题如果满足条件(2)但不满足条件(1),那就称之为NP-hard问题

for example:在某些任意大得棋盘游戏中走出必胜策略,就是一个NP-hard问题。另外,Hamilton回路问题最大团问题也是NP-hard问题。

综述

P类问题随着数据规模增大,算法消耗时间会以常数或者线性关系增长,不会爆炸增长。

NP类问题、NP-complete问题,可能会随着数据规模增大,算法消耗时间成指数级爆炸增长

线性增长(多项式时间复杂度),如$ \mathcal{O}(1) \ \mathcal{O}(n) \ \mathcal{O}(\log(n)) \ \mathcal{O}(n ^ a) $

子图同构问题

内容

对于两张图$ H = (V H, E H) $和$ G = (V G, E G) $,如果存在一个单射$ f : V H \rightarrow V $,如果$ \forall E(u, v) \in E H $,有$ E(f(u), f(v)) \in E_G $,则称图$H$是$G$的子图

无标题-1.png

问题性质

结论:子图同构问题是NP-complete问题

即,NP中任何问题都可以在多项式时间复杂度内转化为子图同构问题。

思路

我们的证明肯定是围绕一个已知的NP-complete问题展开(当然也可以先证明它是一个NP问题,再证明它是一个NP-hard问题以此来得到NP-complete问题),比如以集团决策问题为基础。

无标题.png

证明

设集团决策问题输入图为G(v,e),如果G中包含一个大小为k的完全图,那么判定为true

我们令G1k个顶点的完全图,G2G(v,e),易知,$ k \leq n $(其中nG2中顶点数,kG1完全图中顶点数),从G中生成这两张图需要的时间:$ \mathcal{O}(k ^ 2) = \mathcal{O}(n ^ 2) $,以及边的$ edge = {n \choose k} = \frac{k \times (k - 1)}{2} $,所以仅需要在多项式时间复杂度内就可以创建出两个子图。进一步,如果G1G2的子图同构,那么G中也就有大小为k的完全图,所以如果集团决策问题判定为true,那么该问题在多项式时间下对应的子图同构问题也判定为true,反之亦然。

综上所述,子图同构算法为NP-complete问题!

Ullmann算法思路

这里,我们使用Ullmann算法解决问题

Ullmann算法的基本思路是:设H为子图,G为被匹配图,尝试用邻接矩阵将两张图存下来,之后枚举不同的映射,将H图中映射到G中的点及其附属的边抽离出来得到点数与H相等的图C,再判断是否满足$ \forall E(u, v) \in H \ s.t \ E(f(u), f(v)) \in C $则改映射f判定为true

综上,实现该算法的步骤大致分为:枚举映射,判断结果

枚举映射

定理①

一个映射f是合法映射的必要条件是$ \forall u \in H,d(u) \leq d(f(u)) $


我们可以将输入的两个图用邻接矩阵$ M A \ M B $来存储,并记录每个点的度数,通过判断$ d(u) \leq d(f(u)) $,我们可以得到一个$ k \times n $的矩阵$M$。

定理②

用邻接矩阵表示一个映射f,其满足的必要条件是每一行有一个1,且每一列至多一个1


通过映射矩阵$M _ x$的定义方式,我们很容易得到这个结论

故,我们可以得到枚举的策略:

递归构造映射矩阵$ M _ x $

递归行数$i$,对于每一行,枚举列$j$,如果$ M{i, j} = true $,则可以将映射矩阵的当且位置$ M{x, i, j} $设为true,之后递归到下一行。

递归终止信息是当前递归$ i > k $,此时便开始进行映射矩阵f的判断

当递归会当前行$i$时,将$ M _ {x, i, j} $回退到false,循环进入下一列,以此类推。

判断结果

判断过程我们之前已经提到过了,通过一定的矩阵运算得到从G中剥离出来的仅含有H中点的状态矩阵$ M _ c $

定理③

$ M c = M x (M x M B) ^ T $


证明:

以便我们理清这个变换过程,首先需要明确每个矩阵以及每个过程中能够得到的矩阵的几何含义

$ M {x, i, j} $表示的是$ M x $矩阵第i行,第j列,其状态1(true)/0(false)表示图H的标号为i的点是否映射到图G中的标号为j的点。其是一个$ k \times n $的矩阵

$ M {B, i, j} $表示的是$ M B $矩阵第i行,第j列,其状态1(true)/0(false)表示G中标号为i的点和标号为j的点之间是否有边。其是一个$ n \times n $的矩阵

对于第一步

这两者相乘得到一个$ k \times n $的矩阵,其第i行,第j列为true当且仅当中图Hi映射到G中的k,并且Gkj之间有边。所以,得到的$ M x M B $矩阵就是一个将G中的被映射顶点编号改为H中映射顶点编号的图,其状态1(true)/0(false)H中的i映射到G中之后是否和j有边

接下来我们进行下一步

将得到的矩阵进行转置,则其第i行,第j列,状态1(true)/0(false)表示G中点i是否和H中的j映射后的点有边。其是一个$ n \times k $的矩阵

那么两个相乘得到一个$ k \times k $的矩阵,其第i行,第j列为true当且仅当图Hi映射到G中的k,并且G中的k与映射之前图H中的j有边。所以得到的矩阵$ M x (M x M B) ^ T $就是将点从G中剥离出来的图C的邻接矩阵,且点编号和H中相同,也就是需要的$ M c $

证毕!


之后便可以通过判断是否满足$ \forall M {A, i, j} = true $有$ M {c,i, j} = true $来记录符合条件的映射矩阵了!

时间复杂度

(由于子图同构为NP-complete问题,目前不知道是否存在多项式时间复杂度算法)

最差情况为映射矩阵$M$几乎填满,此时递归时间复杂度为$ \mathcal{O}(n !) $

对于每次判断需要进行矩阵乘法,时间复杂度为$ \mathcal{O}(n ^ 3) $

所以整体的时间复杂度为$ \mathcal{O}(n ! \ n ^ 3) $

代码实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
// By DeNeRATe 杨佳宇轩
#include <iostream>
#include <cmath>
#include <algorithm>
#include <cstdlib>
#include <cstdio>
#include <vector>
#include <windows.h>

#define ll long long
#define de(x) cerr << #x << " = " << x << " "
#define rep(i, a, b) for(int i = a; i <= b; i++)
#define per(i, a, b) for(int i = a; i >= b; i--)
using namespace std;
const int maxn = 12, maxm = 1e5 + 10;

struct node { // 用结构体封装
int squ[maxn][maxn]; // 关系矩阵
int cnt[maxn]; // 图中每个点的度数
int row, line; // 矩阵的行列

inline void clean() { rep(i, 1, row) rep(j, 1, line) { squ[i][j] = 0; } } // 初始化矩阵为零矩阵

friend istream & operator >> (istream &is, node &temp) { // 结构体重载流输入
int u, v;
printf("Please input the number of points in the graph\n");
cin >> temp.row; temp.line = temp.row; // 先输入当前图的点数,之后形成一个deg = 点数的矩阵
printf("Then please input the edge relationship of the graph with \"0 0\" as the end of the order\n");
while(true) { // 输入每一条边,顺便记录每点度数,且形成邻接矩阵
cin >> u >> v;
if(!u || !v) break;
temp.squ[u][v] = temp.squ[v][u] = 1;
temp.cnt[u]++; temp.cnt[v]++;
}
printf("\n");
}

friend ostream & operator << (ostream &os, const node &temp) { // 结构体重载流输出,将矩阵按格式输出
rep(i, 1, temp.row) { rep(j, 1, temp.line)
cout << temp.squ[i][j] << " ";
printf("\n");
}
printf("\n");
}

friend node operator * (node a, node b) { // 结构体中重载乘法为矩阵乘法
node temp;
temp.row = a.row, temp.line = b.line;
temp.clean();
rep(i, 1, temp.row) rep(j, 1, temp.line) {
rep(k, 1, a.line)
temp.squ[i][j] += a.squ[i][k] * b.squ[k][j];
}
return temp;
}

inline node trans() { // 矩阵的转置操作
node temp;
temp.clean(); temp.row = line; temp.line = row;
rep(i, 1, temp.row) rep(j, 1, temp.line) {
temp.squ[i][j] = squ[j][i];
}
return temp;
}
}sta, ed, tr, now;
/*
sta为匹配图
ed为原图,被匹配图
tr为极大映射关系矩阵
now为临时映射矩阵
*/

vector<node> res; // 存放满足条件的映射矩阵
bool jud[maxn]; // 判断临时映射矩阵now中当前列是否已经有了1

inline void init() {
printf("The first matrix is the subgraph and the second is the matched graph\n\n");
Sleep(5000); // 等待5000ms(5s)
cin >> sta >> ed; // 输入这两个图,转化为邻接矩阵
tr.row = sta.row; tr.line = ed.line;
now.row = sta.row; now.line = ed.line; // 映射矩阵规格赋值
rep(i, 1, sta.row) rep(j, 1, ed.line)
if(sta.cnt[i] <= ed.cnt[j])
tr.squ[i][j] = 1; // 如果sta中某点度数小于ed中某点度数则tr极大映射矩阵当前位置为true
}

inline bool check() {
node temp = now * (now * ed).trans(); // 生成仅由sta中的点组成的ed子图
rep(i, 1, sta.row) rep(j, 1, sta.line)
if(sta.squ[i][j] && !temp.squ[i][j]) return false; // 进行判断,满足sta中每一条边temp都有
return true;
}

inline void generate(int dep) { // 每行选取一个1,且每列至多选取一个1
if(dep > tr.row) {
if(check()) res.push_back(now); // 如果这个映射矩阵生成了,那么就用check()函数来进行判断
return;
}
rep(j, 1, tr.line) {
if(!tr.squ[dep][j] || jud[j]) continue;
now.squ[dep][j] = 1;
jud[j] = true;
generate(dep + 1);
now.squ[dep][j] = 0;
jud[j] = false; // 复原,以便枚举到下一个映射矩阵
}
} // 整体递归处理

int main() {
init(); // 初始化函数
generate(1); // 生成所有情况的映射关系,进行判断
if(!res.size()) { // 如果没有满足条件的子图同构的映射
cout << "no mapping relationships\n";
system("pause");
return 0;
}
printf("The mapping relationships are as follows\n");
rep(i, 0, res.size() - 1) { // 输出每个满足条件的映射关系矩阵
printf("%dth:\n", i);
cout << res[i];
}
system("pause");
return 0;
}

// for an idea:连上esp32 将这个图用OLED输出出来,感觉不错,哈哈哈
//时间复杂度:O(deg! * deg ^ 3) 大概1s可处理8个点连成的完全图

/*
示例:
3
1 2
1 3
0 0
4
1 2
1 3
2 3
2 4
3 4
0 0
*/

算法在星图中的应用

​ 在实际应用中,算法直接或间接利用角距、以线段、三角形、四边形等为基本匹配元素,并按照一定方式组织导航特征表。利用这些基本元素的组合,一旦在全天星图中找到唯一符合匹配条件的区域(子图),则它就是观测星图的对应匹配。具体的,大概以多边形算法、三角形算法、匹配组算法等。

参考文献

【简述】【图】P类问题、NP类问题、NP完全问题和NP难问题

P问题、NP问题、NPC问题、NPH问题详解

子图同构问题与Ullmann Algorithm 算法(一)

证明子图同构问题是NP完全的

证明集团决策问题是NP完全的

民用航空与导航技术

一.卫星导航出现之前,飞机如何导航飞行?

1.天文导航

全美航空1594航班机长萨伦伯格在他的传记《最高职责》中说,他飞横贯美国大陆的航线如此之多,以至于在晚上飞行时,只要操纵飞机以使某个星座中某个星星对准驾驶舱风挡玻璃的特定位置,他就能一路飞到目的地。波音737—300,还有相当种类的飞机都在驾驶舱设有观星窗,估计也是这个用途。

2.看地标

当时飞行员都是看着地标飞,比如公路啦,河流啦,这样导航在短途航线还凑合。后来美国开通了一条连通东西海岸的航线送邮件,问题就来了,这么远的航线,飞行员也记不住路啊,所以常常飞着飞着就飞丢了,这可咋办呢?

美国国会一咬牙,就修建了一条横跨美国的箭头带,每个箭头21米多长,黄颜色,旁边还竖着一座燃气灯,飞行员在天上的时候,就一直顺着箭头的方向飞,等看到下一个箭头,就调整方向。所以那时候飞行员除了开飞机,还要不停的伸出脑袋找地面上的箭头。如果找不着,那就只有哭着骂F**k了…

3.惯性导航

惯性导航(inertial navigation) 通过测量飞行器的加速度,并自动进行积分运算,获得飞行器瞬时速度和瞬时位置数据的技术。组成惯性导航系统的设备都安装在运载体内,工作时不依赖外界信息,也不向外界辐射能量,不易受到干扰,是一种自主式导航系统。

4.自动定向机

①NDB(无方向性信标) + ADF(自动方位搜寻器)

原理

NDB向360°方向吸引各路的ADF,飞机上的ADF感受到吸引,就会知道NDB相对于飞机的方位角。通过两台的NDB确定两条直线,也就确定了飞机的位置。

优点

容易安装

缺点

最大误差有时回达到10°左右 ; 传送上的误差(e.g. 到了夜间,由于电离层所反射的空间波增加,此外,打雷伴随的空电影响也较大,常会造成误差)

②VOR(甚高频全向信标) + DME(distance measuring equipment,测距机)(无线电导航)

原理

VOR向360°空间发射两个信号,一个是基准信号,一个是相对于基准信号有“相变”的信号,从0~360°,相变依次增加,飞机上的设备收到这两个信号,一对比,就可以知道自己相对于VOR的方向。配合DME进行距离测量,就可以唯一确定飞机的位置

当然,也可以单独使用3台DME

方法一:确定3个圆,公共交点就是飞机位置

方法二:双曲定位

二.北斗系统相较GPS

目标

近期目标:到2021年底,基本实现北斗系统通用航空低空空域定位及监视应用,完成北斗系统运输航空器追踪监控。

中期目标:到2025年底,全面实现北斗系统通用航空定位、导航与监视应用,基本完成北斗星基增强系统运输航空定位导航应用,全面推动北斗系统运输航空导航及监视应用,实现大型无人机混合空域运行典型场景应用。
远期目标:到2035年底,构建以北斗系统为核心的,与GPS等其他星座兼容互操作的双频多星座GNSS技术应用体系,逐步实现北斗系统民航行业应用“全覆盖、可替代”,为运输、通用航空及无人驾驶航空器飞行提供精确完好、安全可靠的导航服务,全面提升民航安全水平、空域容量、运行效率和服务能力,为新时代民航强国发展提供强大技术支撑,进一步推动北斗全球民航应用。

优势

1.三频信号

北斗使用的是三频信号GPS使用的是双频信号,这是北斗的后发优势。虽然GPS从2010年5月28日发射了第一颗三频卫星,但等到GPS卫星全部老化报废更换为三频卫星还好几年。这几年就是北斗的优势期。三频信号可以更好的消除高阶电离层延迟影响,提高定位可靠性,增强数据预处理能力,大大提高模糊度的固定效率。而且如果一个频率信号出现问题,可使用传统方法利用另外两个频率进行定位,提高了定位的可靠性和抗干扰能力。北斗是全球第一个提供三频信号服务的卫星导航系统

2.有源定位及无源定位

有源定位就是接收机自己需要发射信息与卫星通信,无源定位不需要。北斗一代的有源定位,有源定位技术只要两颗卫星就可以完成定位,但需要信息中心DEM(数字高程模型)数据库支持并参与解算。它在北斗二代上被保留下来,但不作为主要的定位方式。而北斗二代使用的是无源定位,和GPS是一样的,不需要信息中心参与解算,有源定位则作为补充功能。

这个功能的好处是当你观测的卫星质量很差,数量较少时(理论上,无源定位至少要4颗卫星才能解算 XYZ 和时间四个未知参数,实际需要的更多),仍然可以定位。这个功能对于紧急情况会比较有用,比如在山谷中,观测条件非常差,能知道大概位置也是非常重要的。坏处是在战争中会暴露你的位置信息。

3.短报文通信服务

这个是中国卫星导航的原创功能,并且非常实用。08年汶川地震的时候,震区唯一的通讯方式就是北斗一代。这一特色功能毫不意外在二代中保留下来。但是这个功能也是有容量限制的,所以并不适合作为日常通信功能,而是作为紧急情况通信比较合适。基于这个功能,北斗还有一个好处是,不但能知道我在哪,还能让别人知道你在哪。这个功能有利于求救。

4.境内监控

卫星定位系统一般由三部分组成:空间星座部分地面监控部分用户接收机部分。其中,地面地面监控部分又由三大部分组成:监控站主控站注入站

GPS系统在全球建 5个监控站,1个主控站和3个注入站以保证卫星运行,这些站都设在美国国土上,并且在全球分布很均匀。包括美洲大陆的美国本土,太平洋的关岛和夏威夷、印度洋的迭哥枷西亚以及大西洋的阿森松群岛。中国没法把监控站建到全球,所以中国在设计北斗系统时必须考虑到,地面监控部分只建在中国境内,就能够保证整个系统的正常运行。在境外建站也不是不可以,只是就算建了,也只起到提高精度的作用,绝对不能作为控制功能。这本来是北斗的劣势,境内监控是被逼出来的,没有其他选项,但现在成了北斗的安全优势,不用受制于其他国家。

5.分布开通

GPS必须整个系统建成后才能使用。目前北斗的14颗在轨卫星使用了5颗地球静止轨道(GEO)卫星,5颗倾斜地球同步轨道(IGSO)卫星,4颗中高度圆轨道(MEO)卫星。北斗的星座方案来之不易,许院士说当时有几个方案参与竞争,光是方案的修改论证就持续了整整三年,最后确定的这个方案不敢说没有缺点,但绝对是所有方案里最好的一个。

北斗卫星导航系统在这个创新的空间星座支持下,仅仅发射了16颗卫星,就于2012年12月27日在亚太地区正式开通运行。这有利于加快北斗的商用进程,有利于对后续的系统做进一步改进,有利于加快北斗产业链的成熟。毕竟北斗的最大市场肯定是中国嘛,先让北斗系统在亚太地区发展几年,让芯片成熟几年,想推广到全球的时候也会相对容易。而且亚太地区的卫星利用效率肯定也更高,更值得优先投资。

6.其他

亚太地区定位精度高

促进整个制造业升级

——GPS芯片这么好用,我们北斗系统的芯片更应努力进步

——北斗精度不够高很大一部分原因是中国的原子钟

三.北斗系统在民航中的作用

1.在飞机航线路线规划

如果路基导航条件有限,无法搭建地面导航台,就会影响记载导航的服务功能,无法让导航系统按照飞行路线飞行。因此,将北斗卫星导航系统应用在民航导航系统中,可以打破地面导航对机载导航的限制,提高航空领域的利用率。

2.在飞机进离场的RNP精密导航功能

RNP技术是利用飞机自身搭载的导航设备和全球卫星定位系统引导飞机起降的技术。飞行员不需要依靠地面导航设施就能按照精准的定位轨迹进行飞行,即便在能见度很低的情况下,也可以实现精准着陆,提高飞机飞行的安全性和精准性,降低我国航空公司由于天气原因导致飞机航班延误和返航的现象,提高飞机飞行效率

3.在飞机仪表着陆系统(ILS)

又称盲降系统。地面导航系统发射两束无线电信号指引飞机向下滑行和向航道航行,帮助飞机建立一条由跑道向空中飞行的虚拟路径(之前讲过)

四.如何增强

(地基增强系统和星基增强系统都随时全球主流卫星导航系统的“补充”)
卫星导航系统可以通过接收装置收到4颗及以上的导航卫星信号时,计算出所在位置,但这种定位方式精度仅为10m左右,对于大部分行业应用和军用领域而言,这还远远不够。

1.地基增强系统(GBAS)

人们通过在地面建立固定的参考站(CORS站)来获取卫星定位测量时的误差。进而将卫星定位坐标与自身精确坐标对比后的“改正数”结果,发送给接收机。例如,各地测绘、国土、气象等部分建设的国家连续运行基准站CORS网就是属于地基增强系统,后来建立的中国国家北斗地基增强系统也属于地基增强系统

缺点

精度虽然很高,但覆盖范围有一定限制,难以覆盖高空、海上、沙漠、山区,形成了大分为的定位盲区。

2.星基增强系统(SBAS)

通过地球静止轨道(GEO)卫星搭载卫星导航增强信号转发器,可以向用户播发星历误差、卫星钟差、电离层延迟等多种修正信息,弥补地基增强系统的不足

参考文献

在卫星导航出现以前,飞机是靠什么导航飞行的?

百度百科-惯性导航

百度百科-adf

仅用作航空器追踪的北斗机载设备适航要求分析

北斗卫星导航系统及其在民航导航中的应用

了解一下星基增强系统与地基增强系统

初始星图

纸质星图

纸质星图主要分为5种

全天星图

最常见的全天星图将天球分为南北天,分别投影到两个圆上

另外还有一些全天星图将整个天球投影到一个圆上

其可以清楚显示星座相对位置,但天球畸变太严重,只能粗略显示亮恒星位置,因此,实际观测价值不大

四季星图

四季星图更具有实用意义的星图。最常见的四季星图绘制了某一纬度地区的三月、六月、九月、十二月的月中晚上9时的星空。

原理

那么为什么只需要知道每个季度中某一天的同一时刻的星空,就可以画出整个星图呢?

恒星日(地球自转时间) = 23时56分4秒

不同季节的晚上同一时刻看星,星空里出现的星座有所不同。恒星每天提前4分钟出没和中天。就是说,恒星出没和中天的时刻与太阳的出没和中天的时刻是逐日不同的。假定昨天黄昏后7时,牛郎星从东方地平线上升起,那么今天看牛郎星,它在黄昏后6时56分升起;明天则在黄昏后6时52分升起;半月后提前1小时,午后6时就升起了;一个月时于午后5时就升起;一个季度之后,星星出没时间提早了6小时。也就是说,月初黄昏后7时的星空,相当于月中午后6时的星空,也相当于月末(下月月初)午后5时的星空;它又相当于两个月后(第三个月月初)午后3时的星空,……依此类推,它也相当于六个月后月初清晨7时的星空。换句话说,春季黄昏时的星空就是秋季黎明时的星空,冬季黎明时间星空就是秋季子夜时的星空或夏季黄昏时的星空。换一种说法,假若今天19时看到牛郎星在东方地平线附近,在牛郎星西边与牛郎星相距大约90度的大角星在正南方,那么,一个月后同在19时观察星空,我们就会发现大角星已在正南偏西30度的方向;三个月后再在19时观察星空,牛郎星却现现在南方高空中,而大角星则沉落到西北方离地平线很近了。不同月份同一时间星空的形象不同,出现的星座有所变化,因此人们常按春夏秋冬四季把空区分为四季星空。所谓四季星空,就是指每个季节黄昏时候的星空。

由此,我们可以通过一张四季星图,知道一年之内所有时刻的星空图像!

看图方法

注意星图方位标记一般为:上北下南,左东右西

首先应该注意到这张星图的方位标记:上北下南左东右西。这样,当你将这张星图举过头顶,就可以将四个方位与地理方位完美对应了。如果要观察较低的天体,例如北极星,可以将星图标有“北”的一方朝下竖直放置,这时北方地平线附近的天体就可以与星图上的位置对应起来;如果要观察较高的天体,则可以将星图举过头顶,将星图的四个方位与地理方位对应。

图中标注的星等:星等一般分为25等,越小,其亮度越大

另外,这张星图上除了标出了恒星的星等,还标出了一些深空天体。星等采用星点的大小表示,星点 越大,星等越低,恒星越亮;而深空天体则用一些特殊的符号表示。

每月星图

每月星图与四季星图的使用方法是相同的,只不过在适用时间上略有不同:最常见的每月星图绘制了当月月中晚上9时的星空,同时它也适用于月初的晚上10时和月末的晚上8时。

旋转星图

旋转星图巧妙的利用了星空的运行原理,使它可以展示每个时刻的星空。

使用方法

它通常由内外两个盘组成,内盘中间绘有全天星图的一部分,外圈是日期盘;外盘上绘有时间盘。要使用它,只需要将内盘上当天的日期与外盘上当时的时间对齐即可。

旋转星图的优点是它可以用于某一纬度带(一般是绘制纬度 ±5∘ )全年的任何时间。然而它的缺点也很明显:它基本上不能显示除了主要亮星以外的更多信息,而且它是有很大畸变的(注意上图中东西方向的标识在什么位置),所以它的作用比较有限。不过,它也可以直观地显示星空的运行方式

天区图

天区图可以说是在“真正的”天文观测中用途最大的星图

它只显示一小片天区的情况,也正因如此,它可以容纳更多的信息。进而,把涵盖许多天区的天区图编成图册,也就是常用的星图集了。

这是一张6等星图,它包含了大量的信息,例如恒星和深空天体的编号、赤道坐标网格、星座边界,等等。在确认了观测目标的大概位置以后,可以使用这样的天区图精确地定位目标天体。

星图识别基本算法

星图识别算法大致分为两类

子图同构算法

这类算法以星与星之间的角距为边,星为顶点,把观测星图看成是全天星图的子图。它们直接或者间接的利用角距,以线段(角距)、三角形、四边形等为基本匹配元素,并按照一定方式组织导航特征表。利用这些基本元素的组合,一旦在全天星图中找到唯一符合匹配条件的区域(子图),则它就是观测星图的对应匹配。这类算法主要包含多边形算法、三角形算法和匹配组算法等。由于一些星点构成的子图是相同的,这类算法会存在错误匹配的情形,影响其稳定性。

模式识别算法

这类算法为每颗星构造一个独一无二的特征,即星模式,通常以一定邻域内其他星的几个分布特征来构成。这样,星图识别实质上就是在导航星表中寻找与观测星模式最接近的导航星。这类算法最具代表性的为栅格算法。同其他算法相比,栅格算法具备较高识别率,导航星表体积小。

天文望远镜自动寻星

①建立坐标系

借鉴绘制地图的方法,在三维的球面上绘制出一副星图,称为天球

为其赋予一些基本属性

基本属性

赤道平面与天球相交形成的大圆作为基本圆,称为天赤道

平行于天赤道的圆称为赤纬,由天赤道作为赤纬0°向南北方向度量

地球公转轨道面与天球相交形成的大圆称为黄道,黄道与天赤道交与两点,分别是春分和秋分

以地球自转轴作为基本轴,过两个天极的大圆称为赤经,以春分点作为0时,沿着天体东升西落的相反方向进行度量。

得到最基本的坐标系,称为赤道坐标系

②原理

由于地球自转周期为23时56分4秒,所以只需要设置一个起始时,即可推导出任意天体在具体时空中的位置,通常,我们以位于0°经线上的格林尼治恒星时作为标准时间,那么,其他地区的恒星时只需要通过经度换算便可计算得出。

为了引入时间变量,我们在赤道坐标系的基础上稍做变更,以天赤道作为基本圈,以天极为中心将天区分为24时,这样就能定性描述天体的实时坐标,同时,就得到了时角坐标系

我们可以看出,在时角坐标系与赤道坐标系中,天体赤纬相同,而赤经和时角可以通过恒星时进行相互转换

这样一来,我们只需要知道观测地的经纬度和观测时间,以及标准恒星时,就可以通过天体的赤经和赤纬求得天体的具体坐标!

③具体操作

天文望远镜配备赤道仪,其主要跟踪机构为赤经轴赤纬轴

其可以通过内嵌的MCU模块用于计算天体位置,并驱动两轴上的电机,使用前只需要将赤经轴先对准天极方向,使赤经轴和地轴平行,再通过将观测地的经纬度与观测时间作为参量传入MCU,并指定观测天体的赤经赤纬,内置的数据库调用出相关数据并进行计算,即可得出天体的具体坐标,再将坐标数据转换为赤道仪两轴电机需要转动的周期数,即可指向目标。

④误差分析

对于前者,在摆放赤道仪时需要进行极轴的校准

对于后者,通常采用已知天体进行校准,将望远镜先行指向校准星,若校准星未在视野内,则需要通过控制赤道仪手动将校准星移至望远镜视场内,以此时的数据代替原有的计算数据,建立修正后的坐标模型,提高寻星与跟踪的精度(当然也有链接上位机进行更加精确的定位)

参考文献

业余天文学入门(四)| 使用星图

星图识别基本方法

星空的季节性变化

时角坐标系

茫茫夜空中,天文望远镜是如何实现自动寻星的?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
//improvement group
#include <algorithm>
#include <iostream>
#include <cstring>
#include <vector>
#include <cstdio>
#include <ctime>
#include <queue>
#include <deque>
#include <cmath>
#include <map>
#include <unordered_map>

#define ll long long
#define ld long double
#define cl(x, y) memset((x), (y), sizeof(x))
#define rep(i, a, b) for(int i = a; i <= b; i++)
#define per(i, a, b) for(int i = a; i >= b; i--)
#define de(x) cerr << #x << " = " << x << " "
#define inc_mod(x, y) x = ((x - y) % mod + mod) % mod
#define add_mod(x, y) x = (x + y) % mod
#define mul_mod(x, y) x = (x * y) % mod
#define lowbit(x) (x & (-x))
#define inf 0x3f3f3f3f
#define mod_one 998244353
#define mod_two 1000000007
#define rson (x << 1 | 1)
#define lson (x << 1)
using namespace std;

char buffer[100001], *s, *t;
inline char get_char() {
if(s == t) {
t = (s = buffer) + fread(buffer, 1, 100001, stdin);
if(s == t) return EOF;
}
return *s++;
}
inline int fread() {
char ch;
int temp = 0;
for(ch = get_char(); ch < '0' || ch > '9'; ch = get_char());
while(ch >= '0' && ch <= '9') {
temp = (temp << 1) + (temp << 3) + (ch - '0');
ch = get_char();
}
return temp;
}
inline void file() {
freopen(".in", "r", stdin);
freopen(".out", "w", stdout);
}
inline int read_int() {
int temp = 0, fac = 1;
char ch = getchar();
while(ch > '9' || ch < '0') { if(ch == '-') { fac = -1; } ch = getchar(); }
while(ch >= '0' && ch <= '9') { temp = (temp << 1) + (temp << 3) + (ch ^ 48); ch = getchar(); }
return temp * fac;
}
inline ll read_ll() {
ll temp = 0, fac = 1;
char ch = getchar();
while(ch > '9' || ch < '0') { if(ch == '-') { fac = -1; } ch = getchar(); }
while(ch >= '0' && ch <= '9') { temp = (temp << 1) + (temp << 3) + (ch ^ 48); ch = getchar(); }
return temp * fac;
}
inline void write(int now) {
if(now < 0) { putchar('-'), now = -now; }
if(now > 9) { write(now / 10); }
putchar(now % 10 + '0');
}
inline ll mul(ll l, ll r) {
l = (l % mod_one + mod_one) % mod_one;
r = (r % mod_one + mod_one) % mod_one;
ll res = l * r - (ll)((ld)l / mod_one * r + 1e-8) * mod_one;
return res < 0 ? res + mod_one : res;
}

namespace dijkstra {
const ll maxn = 1e4 + 10, maxm = 5e5 + 10;

ll total, side, u, v, w, opt, sta;
ll nxt[maxm << 1], head[maxn], ed[maxm << 1], cur, val[maxm << 1];
bool jud[maxn];
ll dist[maxn];
priority_queue<pair<ll, ll>, vector<pair<ll, ll> >, greater<pair<ll, ll> > > mine;

inline void solve() {
cl(dist, 0x3f);
dist[sta] = 0;
mine.push(make_pair(dist[sta], sta));
while(!mine.empty()) {
pair<ll, ll>now = mine.top();
mine.pop();
if(jud[now.second]) continue;
jud[now.second] = true;
for(ll i = head[now.second]; i; i = nxt[i])
if(dist[ed[i]]>now.first + val[i]) {
dist[ed[i]] = now.first + val[i];
mine.push(make_pair(dist[ed[i]], ed[i]));
}
}
}

inline void add_edge(ll from, ll to, ll temp) {
nxt[++cur] = head[from];
head[from] = cur;
ed[cur] = to;
val[cur] = temp;
}

inline void Main() {
scanf("%lld %lld %lld", &total, &side, &sta);
rep(i, 1, side) { scanf("%lld %lld %lld", &u, &v, &w); add_edge(u, v, w); }
solve();
rep(i, 1, total) { printf("%lld ", dist[i] == inf ? 0x7fffffff : dist[i]); }
}
}
namespace spfa {
const int maxn = 1e4 + 10, maxm = 5e5 + 10;

ll total, side, u, v, w, opt, sta;
ll nxt[maxm << 1], head[maxn], ed[maxm << 1], cur, val[maxm << 1];
bool jud[maxn];
ll dist[maxn];
deque<ll> mine;

inline void solve() {
cl(dist, 0x3f);
dist[sta] = 0;
jud[sta] = true;
mine.push_front(sta);
while(!mine.empty()) {
ll now = mine.front();
mine.pop_front();
jud[now] = false;
for(ll i = head[now]; i; i = nxt[i])
if(dist[ed[i]] > dist[now] + val[i]) {
dist[ed[i]] = dist[now] + val[i];
if(!jud[ed[i]]) {
if(mine.empty() || dist[ed[i]]>dist[mine.front()]) mine.push_back(ed[i]);
else mine.push_front(ed[i]);
jud[ed[i]] = true;
}
}
}
}

inline void add_edge(ll from, ll to, ll temp) {
nxt[++cur] = head[from];
head[from] = cur;
ed[cur] = to;
val[cur] = temp;
}

inline void Main() {
scanf("%lld %lld %lld", &total, &side, &sta);
rep(i, 1, side) { scanf("%lld %lld %lld", &u, &v, &w); add_edge(u, v, w); }
solve();
rep(i, 1, total) { printf("%lld ", dist[i] == inf ? 0x7fffffff : dist[i]); }
}
}
namespace screen_Prime {
const int maxn = 1e8 + 10;

int prime[maxn], cnt;
bool jud[maxn];
int limit, test, u;

inline void solve() {
jud[0] = jud[1] = true;
rep(i, 2, limit) {
if(!jud[i]) { prime[ ++ cnt] = i; }
for(int j = 1; j <= cnt && prime[j] * i <= limit; j++) {
jud[i * prime[j]] = true;
if(!(i % prime[j])) break;
}
}
}

inline void Main() {
scanf("%d %d", &limit, &test);
solve();
while(test--) { scanf("%d", &u); printf("%d\n", prime[u]); }
}
}
namespace kruskal {
const int maxn = 5e3 + 10, maxm = 2e5 + 10;

int total, side, u, v, w, opt;
int fa[maxn], sum, gro;
struct node {
int from, to, val;
friend bool operator < (node a, node b)
{ return a.val < b.val; }
}line[maxm];

inline int find_fa(int now) { return fa[now] == now ? now : fa[now] = find_fa(fa[now]); }
inline void Main() {
scanf("%d %d", &total, &side);
gro = total;
rep(i, 1, side) { scanf("%d %d %d", &line[i].from, &line[i].to, &line[i].val); }
rep(i, 1, total) fa[i] = i;
sort(line + 1, line + side + 1);
rep(i, 1, side) {
int x = find_fa(line[i].from), y = find_fa(line[i].to);
if(x != y) { fa[x] = y; gro--; sum += line[i].val; }
}
if(gro == 1) { printf("%d\n", sum); }
else { printf("orz\n"); }
}
}
namespace prim {
const int maxn = 5e3 + 10, maxm = 2e5 + 10;

int total, side, u, v, w, opt;
int nxt[maxm << 1], head[maxn], ed[maxm << 1], cur, val[maxm << 1];
int dist[maxn], cnt, sum;
bool jud[maxn];
priority_queue<pair<int, int>, vector<pair<int, int> >, greater<pair<int, int> > >mine;

inline void solve() {
cl(dist, 0x3f);
dist[1] = 0;
mine.push(make_pair(dist[1], 1));
while(!mine.empty()) {
pair<int, int>now = mine.top();
mine.pop();
if(jud[now.second]) continue;
jud[now.second] = true;
sum += now.first;
for(int i = head[now.second]; i; i = nxt[i])
if(dist[ed[i]] > val[i]) {
dist[ed[i]] = val[i];
mine.push(make_pair(dist[ed[i]], ed[i]));
}
}
}

inline void add_edge(int from, int to, int temp) {
nxt[++cur] = head[from];
head[from] = cur;
ed[cur] = to;
val[cur] = temp;
}

inline void Main() {
scanf("%d %d", &total, &side);
rep(i, 1, side) { scanf("%d %d %d", &u, &v, &w); add_edge(u, v, w); add_edge(v, u, w); }
solve();
printf("%d\n", sum);
}
}
namespace trisection {
const int maxn = 15;
const double eps = 1e-5;

int total;
double loc[maxn], from, to, ans;

inline double check(double temp) {
double now = 1.0, res = 0.0;
rep(i, 0, total - 1) {
res += now * loc[i];
now *= temp;
}
return res;
}

inline void Main() {
scanf("%d %lf %lf", &total, &from, &to);
per(i, total, 0) { scanf("%lf", &loc[i]); }
rep(i, 0, total - 1) { loc[i] = loc[i + 1] * (i + 1); }
double l = from, r = to;
while(r - l >= eps) {
double mid = (l + r) / 2.0;
if(check(mid)>0) l = mid, ans = mid;
else r = mid;
}
printf("%.5f\n", ans);
}
}
namespace tree_array {
const int maxn = 1e6 + 10;

int fro[maxn];

inline void update(int now, int val) {
for(; now <= maxn - 5; now += lowbit(now))
fro[now] += val;
}

inline int get(int now) {
int res = 0;
for(; now; now -= lowbit(now))
res += fro[now];
return res;
}
}
namespace line_segment_tree {
const int maxn = 1e5 + 10;

ll tree[maxn << 2], tag[maxn << 2], num[maxn];

inline void push_up(ll x) { tree[x] = tree[lson] + tree[rson]; }
inline void build(ll l, ll r, ll x) {
ll mid = (l + r) >> 1;
if(l == r) { tree[x] = num[l]; return; }
build(l, mid, lson);
build(mid + 1, r, rson);
push_up(x);
}

inline void push_down(ll l, ll r, ll x) {
ll mid = (l + r) >> 1;
tag[lson] += tag[x]; tag[rson] += tag[x];
tree[lson] += tag[x] * (mid - l + 1); tree[rson] += tag[x] * (r - mid);
tag[x] = 0;
}

inline void update(ll from, ll to, ll l, ll r, ll x, ll temp) {
if(from <= l && to >= r) { tag[x] += temp; tree[x] += temp * (r - l + 1); return; }
ll mid = (l + r) >> 1;
push_down(l, r, x);
if(from <= mid) update(from, to, l, mid, lson, temp);
if(to > mid) update(from, to, mid + 1, r, rson, temp);
push_up(x);
}

inline ll get(ll from, ll to, ll l, ll r, ll x) {
ll mid = (l + r) >> 1, res = 0;
if(l >= from && r <= to) { res += tree[x]; return res; }
push_down(l, r, x);
if(from <= mid) res += get(from, to, l, mid, lson);
if(to > mid) res += get(from, to, mid + 1, r, rson);
return res;
}
}
namespace kmp {
const int maxn = 1e6 + 10;

char a[maxn], b[maxn];
int lena, lenb;
int lost[maxn];

inline void get_lost() {
int loc = 0;
rep(i, 1, lenb - 1) {
while(loc && b[i] != b[loc]) loc = lost[loc];
if(b[i] == b[loc]) loc++;
lost[i + 1] = loc;
}
}

inline void solve() {
int loc = 0;
rep(i, 0, lena - 1) {
while(loc && a[i] != b[loc]) loc = lost[loc];
if(a[i] == b[loc]) loc++;
if(loc == lenb) { printf("%d\n", i - lenb + 2); }
}
rep(i, 1, lenb) { printf("%d ", lost[i]); }
}

inline void Main() {
scanf("%s", a); lena = strlen(a);
scanf("%s", b); lenb = strlen(b);
get_lost();
solve();
}
}
namespace multiplication_lca {
const int maxn = 5e5 + 10;

int total, test, root, u, v, w, opt;
int nxt[maxn << 1], head[maxn], ed[maxn << 1], cur, val[maxn << 1];
int dep[maxn], anc[maxn][21], len[maxn][20];

inline void dfs(int now, int pre) {
dep[now] = dep[pre] + 1;
rep(i, 1, 20) {
anc[now][i] = anc[anc[now][i - 1]][i - 1];
len[now][i] = len[now][i - 1] + len[anc[now][i - 1]][i - 1];
}
for(int i = head[now]; i; i = nxt[i]) {
if(ed[i] == pre) continue;
anc[ed[i]][0] = now;
len[ed[i]][0] = val[i];
dfs(ed[i], now);
}
}

inline int solve(int x, int y) {
if(dep[x] < dep[y]) swap(x, y);
per(i, 20, 0) { if(dep[anc[x][i]] >= dep[y]) x = anc[x][i]; }
if(x == y) return x;
per(i, 20, 0) if(anc[x][i] != anc[y][i]) x = anc[x][i], y = anc[y][i];
return anc[x][0];
}

inline void add_edge(int from, int to, int temp) {
nxt[++cur] = head[from];
head[from] = cur;
ed[cur] = to;
val[cur] = temp;
}

inline void Main() {
scanf("%d %d %d", &total, &test, &root);
rep(i, 2, total) { scanf("%d %d", &u, &v); add_edge(u, v, 1); add_edge(v, u, 1); }
dfs(root, 0);
while(test--) {
scanf("%d %d", &u, &v);
printf("%d\n", solve(u, v));
}
}
}
namespace negative_loop {
const int maxn = 2e3 + 10, maxm = 3e3 + 10;

ll total, side, u, v, w, opt, test;
ll nxt[maxm << 1], head[maxn], ed[maxm << 1], cur, val[maxm << 1];
bool jud[maxn], flag = true;
ll dist[maxn], cnt[maxn];
queue<ll> mine;

inline void solve() {
cl(dist, 0x3f);
dist[1] = 0;
jud[1] = true;
mine.push(1); cnt[1]++;
while(!mine.empty()) {
ll now = mine.front();
mine.pop();
jud[now] = false;
for(ll i = head[now]; i; i = nxt[i])
if(dist[ed[i]] > dist[now] + val[i]) {
dist[ed[i]] = dist[now] + val[i];
if(!jud[ed[i]]) {
mine.push(ed[i]);
if(++cnt[ed[i]] >= total + 1) { flag = false; return; }
jud[ed[i]] = true;
}
}
}
}

inline void clean() { cl(jud, false); cl(cnt, 0); flag = true; cl(head, 0); cur = 0; while(!mine.empty()) mine.pop(); }
inline void add_edge(ll from, ll to, ll temp) {
nxt[++cur] = head[from];
head[from] = cur;
ed[cur] = to;
val[cur] = temp;
}

inline void Main() {
cin >> test;
while(test--) {
clean();
scanf("%lld %lld", &total, &side);
rep(i, 1, side) { scanf("%lld %lld %lld", &u, &v, &w); add_edge(u, v, w); if(w >= 0) add_edge(v, u, w); }
solve();
if(flag) { printf("NO\n"); }
else { printf("YES\n"); }
}
}
}
namespace matrix {
const int maxn = 4;

ll test, u;
struct node { ll squ[maxn][maxn]; }now, base, cop;

inline void matrix_fast(node &a, node b) {
rep(i, 1, 3) rep(j, 1, 3) cop.squ[i][j] = 0;
rep(i, 1, 3) rep(j, 1, 3) rep(k, 1, 3)
(cop.squ[i][j] += (a.squ[i][k] * b.squ[k][j]) % mod_two) %= mod_two;
rep(i, 1, 3) rep(j, 1, 3) a.squ[i][j] = cop.squ[i][j];
}

inline void solve(ll limit) {
while(limit) {
if(limit & 1) { matrix_fast(now, base); }
matrix_fast(base, base); limit >>= 1;
}
}

inline void clean() {
base.squ[1][1] = base.squ[1][2] = base.squ[2][3] = base.squ[3][1] = 1;
now.squ[1][1] = now.squ[1][2] = now.squ[1][3] = 1;
base.squ[1][3] = base.squ[2][1] = base.squ[2][2] = base.squ[3][2] = base.squ[3][3] = 0;
now.squ[2][1] = now.squ[2][2] = now.squ[2][3] = 0;
now.squ[3][1] = now.squ[3][2] = now.squ[3][3] = 0;
}
inline void Main() {
scanf("%lld", &test);
while(test--) {
clean();
scanf("%lld", &u);
if(u <= 3) { cout << "1" << endl; continue; }
solve(u - 3);
printf("%lld\n", now.squ[1][1]);
}
}
}
namespace st_list {
const int maxn = 1e5 + 10;

int num[maxn];
int anc[maxn][21];
int total, test, u, v;

inline int solve(int l, int r) {
int temp = (log2(double(r - l + 1)));
return max(anc[l][temp], anc[r - (1 << temp) + 1][temp]);
}

inline void Main() {
scanf("%d %d", &total, &test);
rep(i, 1, total) { scanf("%d", &num[i]); anc[i][0] = num[i]; }
for(int j = 1; (1 << j) <= total; j++)
for(int i = 1; i + (1 << j) - 1 <= total; i++)
anc[i][j] = max(anc[i][j - 1], anc[i + (1 << (j - 1))][j - 1]);
while(test--) {
scanf("%d %d", &u, &v);
printf("%d\n", solve(u, v));
}
}
}
namespace antichrist {
const int maxn = 1e5 + 10;

int inv[maxn], fac[maxn], inv_fac[maxn];

inline int fast(int a, int b) {
int res = 1;
while(b) {
if(b & 1) res = res * a % mod_one;
a = a * a % mod_one; b >>= 1;
}
return res % mod_one;
}

inline void Main() {
inv[0] = inv[1] = 1; fac[0] = fac[1] = 1;
rep(i, 2, maxn - 5) {
inv[i] = (mod_one - mod_one / i) * inv[mod_one % i] % mod_one;
fac[i] = fac[i - 1] * i % mod_one;
}
inv_fac[maxn - 5] = fast(fac[maxn - 5], mod_one - 2);
per(i, maxn - 6, 0) { inv_fac[i] = inv_fac[i + 1] * (i + 1) % mod_one; }
}
}
namespace cantor {
const int maxn = 1e6 + 10;

ll num[maxn], fro[maxn];
ll total, fac[maxn], ans;

inline void update(ll now, ll val) { while(now <= maxn - 5) { (fro[now] += val) %= mod_one; now += lowbit(now); } }
inline ll get(ll now) { ll res = 0; while(now) { (res += fro[now]) %= mod_one; now -= lowbit(now); } return res; }
inline void solve() {
rep(i, 1, total) {
ll temp = num[i] - 1 - get(num[i]);
(ans += temp * fac[total - i] % mod_one) %= mod_one;
update(num[i], 1);
}
}

inline void Main() {
scanf("%lld", &total);
fac[0] = 1;
rep(i, 1, total) { scanf("%lld", &num[i]); fac[i] = fac[i - 1] * i % mod_one; }
solve();
printf("%lld\n", ans + 1);
}
}
namespace differential {
const int maxn = 5e3 + 10;

int total, test;
int u, v, w, opt;
int nxt[maxn << 1], head[maxn], ed[maxn << 1], cur, val[maxn << 1];
int cnt[maxn], dist[maxn];
bool vis[maxn], jud = true;
deque<int> temp;

inline void spfa() {
cl(dist, 0x3f);
dist[0] = 0;
temp.push_front(0);
vis[0] = true;
cnt[0] = 1;
while(!temp.empty()) {
int now = temp.front();
temp.pop_front();
vis[now] = false;
for(int i = head[now]; i; i = nxt[i])
if(dist[ed[i]] > dist[now] + val[i]) {
dist[ed[i]] = dist[now] + val[i];
if(!vis[ed[i]]) {
if(temp.empty() || dist[ed[i]] < dist[temp.front()]) temp.push_front(ed[i]);
else temp.push_back(ed[i]);
vis[ed[i]] = true;
if((++cnt[ed[i]]) > total) { printf("No\n"); exit(0); }
}
}
}
}

inline void add_edge(int from, int to, int tot) {
nxt[++cur] = head[from];
head[from] = cur;
ed[cur] = to;
val[cur] = tot;
}

inline void Main() {
scanf("%d %d", &total, &test);
while(test--) {
scanf("%d", &opt);
if(opt == 1) { scanf("%d %d %d", &u, &v, &w); add_edge(u, v, -w); }
else if(opt == 2) { scanf("%d %d %d", &u, &v, &w); add_edge(v, u, w); }
else { scanf("%d %d", &u, &v); add_edge(u, v, 0); }
}
rep(i, 1, total) add_edge(0, i, 0);
spfa();
printf("Yes\n");
}
}
namespace tarjan_scc {
const int maxn = 1e4 + 10, maxm = 1e5 + 10;

int total, side, u, v, w, opt;
int num[maxn], dfn[maxn], low[maxn], dfn_num, col_num, col[maxn], size[maxn];
int nxt[maxm << 1], head[maxn], ed[maxm << 1], cur;
int stack[maxn], top;
bool jud[maxn];

inline void dfs(int now, int pre) {
low[now] = dfn[now] = ++dfn_num;
stack[++top] = now;
jud[now] = true;
for(int i = head[now]; i; i = nxt[i]) {
if(ed[i] == pre) continue;
if(!dfn[ed[i]]) {
dfs(ed[i], now);
low[now] = min(low[now], low[ed[i]]);
} else if(jud[ed[i]])
low[now] = min(low[now], dfn[ed[i]]);
}
if(dfn[now] == low[now]) {
col_num++;
while(stack[top] != now) {
int temp = stack[top--];
jud[temp] = false;
col[temp] = col_num;
size[col_num]++;
}
top--;
jud[now] = false;
col[now] = col_num;
size[col_num]++;
}
}
}
namespace cut_point {
const int maxn = 2e4 + 10, maxm = 1e5 + 10;

int total, side, u, v, w, opt, ans;
int nxt[maxm << 1], head[maxn], ed[maxm << 1], cur;
bool jud[maxn];
int dfn[maxn], low[maxn], dfn_num;

inline void dfs(int now, int pre) {
dfn[now] = low[now] = ++dfn_num;
int child = 0;
for(int i = head[now]; i; i = nxt[i]) {
if(ed[i] == pre) continue;
if(!dfn[ed[i]]) {
child++;
dfs(ed[i], now);
low[now] = min(low[now], low[ed[i]]);
if(pre != 0 && low[ed[i]] >= dfn[now] && !jud[now])
jud[now] = true, ans++;
} else { low[now] = min(low[now], dfn[ed[i]]); }
}
if(pre == 0 && child >= 2 && !jud[now]) { jud[now] = true; ans++; }
}
}
namespace bridge {
const int maxn = 2e4 + 10, maxm = 1e5 + 10;

int nxt[maxm << 1], head[maxn], ed[maxm << 1], cur;
int dfn[maxn], low[maxn], dfn_num;
bool jud[maxm << 1];
int total, side, u, v, w, opt, ans;

inline void dfs(int now, int pre) {
dfn[now] = low[now] = ++dfn_num;
for(int i = head[now]; i; i = nxt[i]) {
if(ed[i] == pre) continue;
if(!dfn[ed[i]]) {
dfs(ed[i], now);
low[now] = min(low[now], low[ed[i]]);
if(low[ed[i]] > dfn[now]) { jud[i] = jud[i ^ 1] = true; ans++; }
} else low[now] = min(low[now], dfn[ed[i]]);
}
}
}
namespace k_nim {
// 这里只打了1 - NIM问题
const int maxn = 1e4 + 10;

int num[maxn], total, test;

inline bool solve() {
int res = 0;
rep(i, 1, total) { res ^= num[i]; }
return res;
}

inline void Main() {
scanf("%d", &test);
while(test--) {
scanf("%d", &total);
rep(i, 1, total) scanf("%d", &num[i]);
if(solve()) { printf("Yes\n"); }
else { printf("No\n"); }
}
}
}
namespace gcd {
inline int gcd(int x, int y) {
return (!y) ? x : gcd(y, x % y);
}
}
namespace ex_gcd {
ll test, a, b, c, x, y, r, d, cnt;

inline ll init(ll x, ll y) {
if(!y) { x = 1; y = 0; return x; }
ll p = init(y, x % y);
ll temp = y; y = x - (x / y) * y; x = temp;
return p;
}

inline void solve() {
x = y = r = d = cnt = 0;
r = init(a, b);
if(c % r) { printf("-1\n"); return; }
ll x0 = x * (c / r), y0 = y * (c / r);
ll p = b / r, q = a / r;
if(x0 < 0) { ll k = (ceil)((1.0 - x0) / p); x0 += p * k; y0 -= q * k; }
else { ll k = (x0 - 1) / p; x0 -= p * k; y0 += q * k; }
if(y0 > 0) {
printf("%lld ", (y0 - 1) / q + 1);
printf("%lld %lld %lld %lld\n", x0, (y0 - 1) % q + 1, x0 + p * ((y0 - 1) / q), y0);
} else {
printf("%lld ", x0);
int o = ceil((1.0 - y0) / q);
printf("%lld\n", y0 + q * o);
}
}

inline void Main() {
scanf("%lld", &test);
while(test--) {
scanf("%lld %lld %lld", &a, &b, &c);
solve();
}
}
}
namespace fhq_treap {
const int maxn = 1e5 + 10;

int test, u, v, w, opt, root;
int weight[maxn], val[maxn], size[maxn], child[maxn][2], cnt;

inline void update(int now) { size[now] = size[child[now][1]] + size[child[now][0]] + 1; }
inline int new_node(int temp) { weight[++cnt] = rand(); val[cnt] = temp; size[cnt] = 1; return cnt; }
inline void split(int now, int limit, int &a, int &b) {
if(!now) { a = b = 0; return; }
if(val[now] <= limit) { a = now; split(child[now][1], limit, child[now][1], b); }
else { b = now; split(child[now][0], limit, a, child[now][0]); }
update(now);
}

inline int merge(int a, int b) {
if(!a || !b) { return a + b; }
if(weight[a] < weight[b]) { child[a][1] = merge(child[a][1], b); update(a); return a; }
else { child[b][0] = merge(a, child[b][0]); update(b); return b; }
}

inline int rank(int now, int limit) {
while(true) {
if(size[child[now][0]] >= limit) now = child[now][0];
else if(size[child[now][0]] + 1 == limit) return val[now];
else limit -= size[child[now][0]] + 1, now = child[now][1];
}
}

inline void Main() {
scanf("%d", &test);
while(test--) {
scanf("%d %d", &opt, &u);
int x = 0, y = 0, z = 0;
if(opt == 1) { split(root, u - 1, x, y); root = merge(merge(x, new_node(u)), y); }
else if(opt == 2) { split(root, u - 1, x, y); split(y, u, y, z); root = merge(merge(x, merge(child[y][0], child[y][1])), z); }
else if(opt == 3) { split(root, u - 1, x, y); printf("%d\n", size[x] + 1); root = merge(x, y); }
else if(opt == 4) { printf("%d\n", rank(root, u)); }
else if(opt == 5) { split(root, u - 1, x, y); printf("%d\n", rank(x, size[x])); root = merge(x, y); }
else { split(root, u, x, y); printf("%d\n", rank(y, 1)); root = merge(x, y); }
}
}
}
namespace descartes {
const int maxn = 1e7 + 10;

int child[maxn][2], num[maxn];
int stack[maxn], top;
int total, u, v, w, opt;
ll ans_one, ans_two;

inline void Main() {
scanf("%d", &total);
rep(i, 1, total) {
num[i] = read_int();
int k = top;
while(k && num[stack[k]] >= num[i]) { k--; }
if(k) { child[stack[k]][1] = i; }
if(k != top) { child[i][0] = stack[k + 1]; }
top = k;
stack[++top] = i;
}
rep(i, 1, total) { ans_one ^= 1ll * i * (child[i][0] + 1); ans_two ^= 1ll * i * (child[i][1] + 1); }
printf("%lld %lld\n", ans_one, ans_two);
}
}
namespace minimalist_representation {
const int maxn = 3e5 + 10;

int num[maxn];
int len, pos_one, pos_two, k, ans;

inline void solve() {
pos_one = 0, pos_two = 1, k = 0;
while(pos_one < len && pos_two < len && k < len) {
if(num[(pos_one + k) % len] == num[(pos_two + k) % len]) k++;
else {
(num[(pos_one + k) % len] < num[(pos_two + k) % len]) ? pos_two = (pos_two + k + 1) : pos_one = (pos_one + k + 1);
if(pos_one == pos_two) pos_one++;
k = 0;
}
}
ans = min(pos_one, pos_two);
rep(i, 0, len - 1) { printf("%d ", num[(ans + i) % len]); }
}

inline void Main() {
scanf("%d", &len);
rep(i, 0, len - 1) scanf("%d", &num[i]);
solve();
}
}
namespace manacher {
const int maxn = 1.5e7 + 10;

char num[maxn << 1];
int len, rou[maxn << 1];
int temp, dist, ans;

inline void char_read() {
char ch = getchar();
num[0] = '~'; num[len = 1] = '|';
while(ch<'a' || ch>'z') ch = getchar();
while(ch >= 'a' && ch <= 'z') num[++len] = ch, num[++len] = '|', ch = getchar();
}

inline void solve() {
rep(i, 1, len) {
if(i <= dist) { rou[i] = min(dist - i + 1, rou[(temp << 1) - i]); }
while(num[i + rou[i]] == num[i - rou[i]]) rou[i]++;
if(dist < i + rou[i]) temp = i, dist = i + rou[i] - 1;
ans = max(ans, rou[i]);
}
printf("%d\n", ans - 1);
}

inline void Main() {
char_read();
solve();
}
}
namespace crt {
ll ans, m = 1, total, a[12], c[12];

inline ll ex_gcd(ll a, ll b, ll &x, ll &y) {
if(!b) { x = 1;y = 0; return a; }
ll res = ex_gcd(b, a % b, y, x);
y -= (a / b) * x;
return res;
}

inline ll china(ll *w, ll *r) {
for(int i = 1; i <= total; i++) m *= w[i];
for(int i = 1; i <= total; i++){
ll m1 = m / w[i], x, y;
ll d = ex_gcd(m1, w[i], x, y);
ans = (ans + m1 * x * r[i]) % m;
}
if(ans < 0) ans += m;
return ans;
}

inline void Main() {
scanf("%lld", &total);
for(int i = 1; i <= total; i++) scanf("%lld %lld", &a[i], &c[i]);
printf("%lld", china(a, c));
}
}
namespace ex_crt {
const int maxn = 1e5 + 10;

ll a[maxn], m[maxn], x, y;
ll total;

inline ll ex_gcd(ll x, ll y) {
if(!y) { x = 1; y = 0; return x; }
ll r = ex_gcd(y, x % y);
ll temp = y; y = x - (x / y) * y; x = temp;
return r;
}

inline void solve() {
ll a1 = a[1], m1 = m[1];
rep(i, 2, total) {
x = y = 0;
ll a2 = a[i], m2 = m[i];
ll r = ex_gcd(m1, m2);
if((a2 - a1) % r) { printf("-1\n"); return; }
ll t = m2 / r, p = (a2 - a1) / r;
ll x0 = (p * x % t + t) % t;
a1 = m1 * x0 + a1;
m1 = m1 * m2 / r;
if(a1 < 0) a1 += m1;
}
printf("%lld\n", a1 % m1);
}

inline void Main() {
scanf("%lld", &total);
rep(i, 1, total) { scanf("%lld %lld", &m[i], &a[i]); }
solve();
}
}
namespace ac_automaton {
const int maxn = 2e5 + 10, maxm = 2e6 + 10;

char num[maxn], temp[maxm];
int len, total, ans[maxn];
int child[maxn][30], lost[maxn], sig[maxn], size;
int queue[maxn], head = 1, tail;

inline void update(int id) {
int loc = 0, s = strlen(num + 1);
rep(i, 1, s) {
int to = (num[i] - 'a' + 1);
if(!child[loc][to]) child[loc][to] = ++size;
loc = child[loc][to];
}
sig[id] = loc;
}

inline void get_lost() {
rep(i, 1, 26) if(child[0][i]) { queue[++tail] = child[0][i]; }
while(head <= tail) {
int now = queue[head++];
rep(i, 1, 26) {
if(child[now][i]) { lost[child[now][i]] = child[lost[now]][i]; queue[++tail] = child[now][i]; }
else { child[now][i] = child[lost[now]][i]; }
}
}
}

inline void solve() {
int now = 0;
rep(i, 1, len) {
int to = (temp[i] - 'a' + 1);
now = child[now][to];
ans[now]++;
}
per(i, size, 1) ans[lost[queue[i]]] += ans[queue[i]];
}

inline void Main() {
scanf("%d", &total);
rep(i, 1, total) { scanf("%s", num + 1); update(i); }
get_lost();
scanf("%s", temp + 1); len = strlen(temp + 1);
solve();
rep(i, 1, total) { printf("%d\n", ans[sig[i]]); }
}
}
namespace sam {
const int maxn = 2e6 + 10;

int total, u, v, w, opt;
ll ans;
char num[maxn];
struct node {
int ch[30];
int len, cnt, lost;
}state[maxn << 1];
int size, last;
int nxt[maxn << 1], head[maxn << 1], ed[maxn << 1], cur;

inline void update(int now) {
int cur = ++size;
state[cur].len = state[last].len + 1;
state[cur].cnt = 1;
int loc = last;
while(loc != -1 && !state[loc].ch[now]) {
state[loc].ch[now] = cur;
loc = state[loc].lost;
}
if(loc == -1) state[cur].lost = 0;
else {
int to = state[loc].ch[now];
if(state[to].len == state[loc].len + 1) state[cur].lost = to;
else {
int clone = ++size;
state[clone].lost = state[to].lost;
rep(i, 1, 26) state[clone].ch[i] = state[to].ch[i];
state[clone].len = state[loc].len + 1;
while(loc != -1 && state[loc].ch[now] == to) {
state[loc].ch[now] = clone;
loc = state[loc].lost;
}
state[cur].lost = state[to].lost = clone;
}
}
last = cur;
}

inline void solve(int now) {
for(int i = head[now]; i; i = nxt[i]) {
solve(ed[i]);
state[now].cnt += state[ed[i]].cnt;
}
if(state[now].cnt != 1) ans = max(ans, 1ll * state[now].len * state[now].cnt);
}

inline void add_edge(int from, int to) {
nxt[++cur] = head[from];
head[from] = cur;
ed[cur] = to;
}

inline void Main() {
scanf("%s", num + 1);
total = strlen(num + 1);
state[0].lost = -1;
rep(i, 1, total) { update(num[i] - 'a' + 1); }
rep(i, 1, size) add_edge(state[i].lost, i);
solve(0);
printf("%d\n", ans);
}
}
namespace pam {
const int maxn = 5e5 + 10;

char num[maxn];
struct node {
int ch[30];
int len, cnt, link;
}state[maxn];
int cop[maxn], total, size = 1, k, temp, pos, last;

inline int get(int now) {
while(cop[pos] != cop[pos - state[now].len - 1]) now = state[now].link;
return now;
}

inline void update(int now) {
cop[++pos] = now;
int loc = get(last);
if(!state[loc].ch[now]) {
int cur = ++size;
state[cur].len = state[loc].len + 2;
int to = get(state[loc].link);
state[cur].link = state[to].ch[now];
state[loc].ch[now] = cur;
state[cur].cnt = state[state[cur].link].cnt + 1;
temp = cur;
} else { temp = state[loc].ch[now]; }
last = state[loc].ch[now];
}

inline void Main() {
scanf("%s", num + 1); total = strlen(num + 1);
state[0].link = state[1].link = 1;
state[1].len = -1;
rep(i, 1, total) {
num[i] = (char)(((int)num[i] - 97 + k) % 26 + 97);
update(num[i] - 'a' + 1);
printf("%d ", k = state[temp].cnt);
}
}
}
namespace lcs {
const int maxn = 1e5 + 10;

int loc[maxn] ,cop[maxn];
int fro[maxn];
int total, ans, u, v, w, opt;

inline void update(int now, int temp) {
while(now <= maxn - 5) {
fro[now] = max(fro[now], temp);
now += lowbit(now);
}
}

inline int get(int now) {
int res = 0;
while(now) {
res = max(res, fro[now]);
now -= lowbit(now);
}
return res;
}

inline void Main() {
total = read_int();
rep(i, 1, total) {
u = read_int();
loc[u] = i;
}
rep(i, 1, total) {
u = read_int();
cop[i] = loc[u];
}
rep(i, 1, total) {
int res = get(cop[i]);
ans = max(ans, res + 1);
update(cop[i], res + 1);
}
write(ans);
}
}
namespace prufer {
const int maxn = 5e6 + 10;

int total, u, v, w, opt;
int fa[maxn], sig[maxn];
int loc = 1, d[maxn], vis[maxn];
ll ans;

inline void fa_prufer(){
rep(i, 1, total - 1) {
fa[i] = read_int();
d[i]++;
d[fa[i]]++;
}
rep(i, 1, total)
if(d[i] == 1) {
loc = i;
break;
}
rep(i, 1, total - 2) {
while(d[loc] != 1) loc++;
sig[i] = fa[loc];
d[loc]--;
while(i < total - 1 && (--d[sig[i]]) == 1 && sig[i] < loc) {
sig[i + 1] = fa[sig[i]];
i++;
}
}
rep(i, 1, total - 2) ans ^= (1ll * i * sig[i]);
printf("%lld\n", ans);
}

inline void prufer_fa() {
rep(i, 1, total - 2) sig[i] = read_int(), vis[sig[i]]++;
rep(i, 1, total) {
if(!vis[i] && !loc) loc = i;
d[i] = vis[i] + 1;
}
sig[total - 1] = total;
rep(i, 1, total - 1) {
while(d[loc] != 1) loc++;
fa[loc] = sig[i];
d[loc]--;
while(i < total && (--d[sig[i]]) == 1 && sig[i] < loc) {
fa[sig[i]] = sig[i + 1];
i++;
}
}
rep(i, 1, total - 1) ans ^= (1ll * i * fa[i]);
printf("%lld\n", ans);
}

inline void Main() {
total = read_int();
opt = read_int();
if(opt == 1) fa_prufer();
else prufer_fa();
}
}
namespace convex_hull {
const int maxn = 1e5 + 10;

int total, u, v, w, opt;
struct node {
double x, y;

friend double operator ^ (node a, node b) { return a.x * b.y - a.y * b.x; }
friend double operator * (node a, node b) { return a.x * b.x + a.y + b.y; }
friend node operator + (node a, node b) { return node { a.x + b.x, a.y + b.y }; }
friend node operator - (node a, node b) { return node { a.x - b.x, a.y - b.y }; }
friend bool operator < (node a, node b) {
if(a.x == b.x) return a.y < b.y;
else return a.x < b.x;
}
}dot[maxn];
int stack[maxn], top;
double ans;
bool vis[maxn];

inline double calc(int a, int b, int c) {
return (dot[b] - dot[a]) ^ (dot[c] - dot[a]);
}

inline double distance(int a, int b) {
return sqrt((dot[a].x - dot[b].x) * (dot[a].x - dot[b].x) + (dot[a].y - dot[b].y) * (dot[a].y - dot[b].y));
}

inline void solve() {
stack[top = 1] = 1;
vis[1] = true;
rep(i, 2, total) {
while(top >= 2 && calc(stack[top - 1], stack[top], i) < double(0)) vis[stack[top--]] = false;
stack[++top] = i;
vis[i] = true;
}
int temp = top;
per(i, total - 1, 1) {
while(top > temp && calc(stack[top - 1], stack[top], i) < double(0)) vis[stack[top--]] = false;
stack[++top] = i;
vis[i] = true;
}
rep(i, 1, top - 1) ans += distance(stack[i], stack[i + 1]);
printf("%.2f\n", ans);
}

inline void Main() {
total = read_int();
rep(i, 1, total) scanf("%lf %lf", &dot[i].x, &dot[i].y);
sort(dot + 1, dot + total + 1);
solve();
}
}
namespace subsequence_automata {
const int maxn = 1e6 + 10;

int num[maxn], cop[maxn];
int total, len, u, v, w, opt, type, test, limit;
vector<int> loc[maxn];

inline void Main() {
type = read_int();
total = read_int(); test = read_int(); limit = read_int();
rep(i, 1, total) num[i] = read_int();
rep(i, 1, total) loc[num[i]].push_back(i);
while(test--) {
len = read_int();
rep(i, 1, len) cop[i] = read_int();
int last = 0;
bool jud = true;
rep(i, 1, len) {
vector<int>::iterator iter = upper_bound(loc[cop[i]].begin(), loc[cop[i]].end(), last);
if(iter == loc[cop[i]].end()) { jud = false; break; }
else last = *iter;
}
if(!jud) printf("No\n");
else printf("Yes\n");
}
}
}
namespace lichao_line_segment_tree {
const int maxn = 5e4 + 10;

int test, w;
double u, v;
struct node {
double k, b;

inline double calc(int x)
{ return k * (x - 1) + b; }
}line[maxn << 2];
char opt[10];

inline void update(int x, int l, int r, node now) {
int mid = (l + r) >> 1;
if(now.calc(l) >= line[x].calc(l) && now.calc(r) >= line[x].calc(r)) {
line[x] = now;
return;
}
if(l == r) return;
if(now.calc(mid) >= line[x].calc(mid)) swap(now, line[x]);
if(now.calc(l) >= line[x].calc(l)) update(lson, l, mid, now);
if(now.calc(r) >= line[x].calc(r)) update(rson, mid + 1, r, now);
}

inline double get(int x, int l, int r, int loc) {
int mid = (l + r) >> 1;
double res = line[x].calc(loc);
if(loc < mid) return max(res, get(lson, l, mid, loc));
if(loc > mid) return max(res, get(rson, mid + 1, r, loc));
return res;
}

inline void Main() {
test = read_int();
while(test--) {
scanf("%s", opt + 1);
if(opt[1] == 'P') {
scanf("%lf %lf", &u, &v);
update(1, 1, maxn - 5, node{ v, u });
} else {
w = read_int();
int temp = int(get(1, 1, maxn - 5, w)) / 100;
printf("%d\n", temp);
}
}
}
}
namespace linear_base {
const int maxn = 60;

ll base[maxn], num[maxn];
ll ans, total;

inline void insert(ll now) {
per(i, maxn - 2, 0) {
if(!((now >> i) & 1)) continue;
if(!base[i]) {
base[i] = now;
break;
} else now ^= base[i];
}
}

inline void Main() {
total = read_ll();
rep(i, 1, total) {
num[i] = read_ll();
insert(num[i]);
}
per(i, maxn - 2, 0) {
if(ans & (1ll << i)) continue;
else ans ^= base[i];
}
printf("%lld\n", ans);
}
}
namespace line_segment_tree_partition {
const int maxn = 1e5 + 10;

struct node { int x, y; }line[maxn];
vector<node> mine[maxn << 2];
vector<int> time[maxn];
int total, side, u, v, w, opt, test;
int fa[maxn], dep[maxn], size[maxn];
pair<int, int> con[maxn];
int stack[maxn], top;

inline int find_fa(int now) {
if(fa[now] == now) return now;
else return find_fa(fa[now]);
}

inline void merge(int x, int y) {
if(dep[x] < dep[y]) swap(x, y);
fa[y] = x;
stack[++top] = y;
size[x] += size[y];
if(dep[x] == dep[y]) dep[x]++, con[y] = make_pair(1, size[y]);
else con[y] = make_pair(0, size[y]);
}

inline void update(int x, int l, int r, int from, int to, int loc) {
if(from <= l && to >= r) { mine[x].push_back(line[loc]); return; }
int mid = (l + r) >> 1;
if(from <= mid) update(lson, l, mid, from, to, loc);
if(to > mid) update(rson, mid + 1, r, from, to, loc);
}

inline void solve(int x, int l, int r) {
int last = top;
rep(i, 0, int(mine[x].size()) - 1) {
node now = mine[x][i];
int a = find_fa(now.x), b = find_fa(now.y);
if(a != b) merge(a, b);
}
if(l == r) {
if(size[find_fa(1)] != total) printf("Disconnected\n");
else printf("Connected\n");
}
int mid = (l + r) >> 1;
if(r > l) {
solve(lson, l, mid);
solve(rson, mid + 1, r);
}
for(; top > last; top--) {
dep[fa[stack[top]]] -= con[stack[top]].first;
size[fa[stack[top]]] -= con[stack[top]].second;
fa[stack[top]] = stack[top];
con[stack[top]] = make_pair(0, 0);
}
}

inline void Main() {
total = read_int(); side = read_int();
rep(i, 1, side) line[i].x = read_int(), line[i].y = read_int();
rep(i, 1, total) fa[i] = i, size[i] = 1, dep[i] = 1;
test = read_int();
rep(i, 1, test) {
opt = read_int();
rep(j, 1, opt) {
u = read_int();
time[u].push_back(i);
}
}
rep(i, 1, side) {
u = 0; v = 0;
rep(j, 0, int(time[i].size()) - 1) {
v = time[i][j];
if(v == u + 1) { u = v; continue; }
update(1, 1, test, u + 1, v - 1, i);
u = v;
}
if(v != test) update(1, 1, test, u + 1, test, i);
}
solve(1, 1, test);
}
}
namespace tree_chain_splitting {
const int maxn = 1e5 + 10;

int total, test, root, mod, u, v, w, opt;
int num[maxn];
int dfn[maxn], top[maxn], son[maxn], fa[maxn], size[maxn], dfn_num, dot[maxn], dep[maxn];
int head[maxn], nxt[maxn << 1], ed[maxn << 1], cur;
int sum[maxn << 2], tag[maxn << 2];

inline void dfs_one(int now, int pre) {
dep[now] = dep[pre] + 1;
size[now] = 1;
fa[now] = pre;
for(int i = head[now]; i; i = nxt[i]) {
if(ed[i] == pre) continue;
dfs_one(ed[i], now);
size[now] += size[ed[i]];
if(size[ed[i]] > size[son[now]]) son[now] = ed[i];
}
}

inline void dfs_two(int now, int pre, int front) {
top[now] = front;
dfn[now] = ++dfn_num;
dot[dfn_num] = now;
if(son[now]) dfs_two(son[now], now, front);
for(int i = head[now]; i; i = nxt[i]) {
if(ed[i] == pre || ed[i] == son[now]) continue;
dfs_two(ed[i], now, ed[i]);
}
}

inline void push_up(int x) { sum[x] = (sum[lson] + sum[rson]) % mod; }
inline void build(int x, int l, int r) {
if(l == r) { sum[x] = num[dot[l]] % mod; return; }
int mid = (l + r) >> 1;
build(lson, l, mid);
build(rson, mid + 1, r);
push_up(x);
}

inline void push_down(int x, int l, int r) {
if(tag[x] == 0) return;
int mid = (l + r) >> 1;
add_mod(tag[lson], tag[x]);
add_mod(tag[rson], tag[x]);
add_mod(sum[lson], tag[x] * (mid - l + 1) % mod);
add_mod(sum[rson], tag[x] * (r - mid) % mod);
tag[x] = 0;
}

inline void update(int x, int l, int r, int from, int to, int temp) {
if(l >= from && r <= to) {
add_mod(tag[x], temp);
add_mod(sum[x], temp * (r - l + 1));
return;
}
int mid = (l + r) >> 1;
push_down(x, l, r);
if(from <= mid) update(lson, l, mid, from, to, temp);
if(to > mid) update(rson, mid + 1, r, from, to, temp);
push_up(x);
}

inline int get(int x, int l, int r, int from, int to) {
if(l >= from && r <= to) return sum[x];
int mid = (l + r) >> 1, res = 0;
push_down(x, l, r);
if(from <= mid) add_mod(res, get(lson, l, mid, from, to));
if(to > mid) add_mod(res, get(rson, mid + 1, r, from, to));
push_up(x);
return res;
}

inline void add(int x, int y, int temp) {
while(top[x] != top[y]) {
if(dep[top[x]] < dep[top[y]]) swap(x, y);
update(1, 1, total, dfn[top[x]], dfn[x], temp);
x = fa[top[x]];
}
if(dep[x] < dep[y]) swap(x, y);
update(1, 1, total, dfn[y], dfn[x], temp);
}

inline int query(int x, int y) {
int res = 0;
while(top[x] != top[y]) {
if(dep[top[x]] < dep[top[y]]) swap(x, y);
add_mod(res, get(1, 1, total, dfn[top[x]], dfn[x]));
x = fa[top[x]];
}
if(dep[x] < dep[y]) swap(x, y);
add_mod(res, get(1, 1, total, dfn[y], dfn[x]));
return res;
}

inline void add_edge(int from, int to) {
nxt[++cur] = head[from];
head[from] = cur;
ed[cur] = to;
}

inline void Main() {
total = read_int(); test = read_int();
root = read_int(); mod = read_int();
rep(i, 1, total) num[i] = read_int();
rep(i, 2, total) {
u = read_int(); v = read_int();
add_edge(u, v);
add_edge(v, u);
}
dfs_one(root, 0);
dfs_two(root, 0, root);
build(1, 1, total);
while(test--) {
opt = read_int();
if(opt == 1) { u = read_int(); v = read_int(); w = read_int(); add(u, v, w); }
else if(opt == 2) { u = read_int(); v = read_int(); printf("%d\n", query(u, v)); }
else if(opt == 3) { u = read_int(); v = read_int(); update(1, 1, total, dfn[u], dfn[u] + size[u] - 1, v); }
else { u = read_int(); printf("%d\n", get(1, 1, total, dfn[u], dfn[u] + size[u] - 1)); }
}
}
}
namespace two_sat {
const int maxn = 2e6 + 10;

int total, test, a, b, c, d, u, v, w, opt;
int nxt[maxn << 1], head[maxn << 1], ed[maxn << 1], cur;
int dfn[maxn << 1], low[maxn << 1], dfn_num, col[maxn << 1], col_num;
int stack[maxn << 1], top;
bool jud[maxn << 1];

inline void tarjan(int now, int pre) {
dfn[now] = low[now] = ++dfn_num;
stack[++top] = now;
jud[now] = true;
for(int i = head[now]; i; i = nxt[i]) {
if(ed[i] == pre) continue;
if(!dfn[ed[i]]) {
tarjan(ed[i], now);
low[now] = min(low[now], low[ed[i]]);
} else if(jud[ed[i]]) low[now] = min(low[now], dfn[ed[i]]);
}
if(low[now] == dfn[now]) {
col[now] = ++col_num;
jud[now] = false;
while(stack[top] != now) {
jud[stack[top]] = false;
col[stack[top]] = col_num;
top--;
}
top--;
}
}

inline void add_edge(int from, int to) {
nxt[++cur] = head[from];
head[from] = cur;
ed[cur] = to;
}

inline void Main() {
total = read_int();
test = read_int();
rep(i, 1, test) {
a = read_int(); b = read_int();
c = read_int(); d = read_int();
add_edge(a + (b ^ 1) * total, c + d * total);
add_edge(c + (d ^ 1) * total, a + b * total);
}
rep(i, 1, (total << 1))
if(!dfn[i]) tarjan(i, 0);
bool flag = true;
rep(i, 1, total)
if(col[i] == col[i + total]) {
printf("IMPOSSIBLE\n");
exit(0);
}
printf("POSSIBLE\n");
rep(i, 1, total)
printf("%d ", col[i] > col[i + total]);
}
}

namespace ex_bsgs {
ll a, b, p, k, limit, d, now, c, ans;
bool jud;

unordered_map<ll,ll> cube;

inline ll gcd(ll x, ll y) {
return !y ? x : gcd(y, x % y);
}

inline ll fast(ll x, ll y, ll p) {
ll res = 1, step = x % p;
while(y) {
if(y & 1) res = res * step % p;
step = step * step % p;
y >>= 1;
}
return res % p;
}

inline void Main() {
while(scanf("%lld %lld %lld", &a, &p, &b) && (a || b || p)) {
jud = false;
cube.clear();
c = 1, d = gcd(a, p), k = 0;
if(b == 1) { printf("0\n"); continue; }
while(d != 1) {
if(b % d) {
printf("No Solution\n");
jud = true;break;
}
b /= d; p /= d; c = c * (a / d) % p; k++; d = gcd(a, p);
if(b == c) {
printf("%lld\n", k);
jud = true;
break;
}
}
if(jud) continue;
limit = ceil(sqrt(p));
now = b;
for(int i = 0; i <= limit; i++) {
cube[now] = i + 1;
now = now * a % p;
}
ll stan = fast(a, limit, p);
now = c; ans = -1;
for(int i = 1; i <= limit; i++) {
now = now * stan % p;
if(cube[now]) {
ans = i * limit - cube[now] + 1 + k;
break;
}
}
if(ans == -1) printf("No Solution\n");
else printf("%lld\n", ans);
}
}
}

namespace lucas {
const ll maxn = 1e5 + 10;

ll fac[maxn], inv_fac[maxn];
ll test, u, v, w, opt, mod;

inline ll c(ll n, ll m) {
if(n < m) return 0;
else return fac[n] * inv_fac[m] % mod * inv_fac[n - m] % mod;
}

inline ll solve(ll n, ll m) {
if(!m) return 1;
return c(n % mod, m % mod) * solve(n / mod, m / mod) % mod;
}

inline ll fast(ll a,ll b) {
ll res = 1;
while(b) {
if(b & 1) res = res * a % mod;
a = a * a % mod;
b >>= 1;
}
return res % mod;
}

inline void Main() {
test = read_ll();
while(test--) {
u = read_ll();
v = read_ll();
mod = read_ll();
fac[0] = 1;
rep(i, 1, mod - 1) fac[i] = fac[i - 1] * i % mod;
inv_fac[mod - 1] = fast(fac[mod - 1], mod - 2);
per(i, mod - 2, 0) inv_fac[i] = inv_fac[i + 1] * (i + 1) % mod;
printf("%lld\n", solve(u + v, u));
}
}
}


signed main() {
// file();
// ios::sync_with_stdio(false);
// srand(time(NULL));
two_sat::Main();
// fclose(stdin);
// fclose(stdout);
// system("pause");
return 0;
}