LibreOJ NOIP Round #1」七曜圣贤
B. 七曜圣贤
内存限制:1024 MiB时间限制:2500 ms标准输入输出题目类型:传统评测方式:文本比较
题目描述
本题 C/C++ 时限 2.5 秒,Pascal 时限 5 秒。最后将改时限重测所有 Pascal 提交。
不知道大家有没有听过物凄系列的一首歌,帕秋莉用卡车给博丽老板运货的故事。
又一次,卡车司机帕秋莉被拜托。红魔馆之主蕾米莉亚喜欢喝红茶,一天她要求帕秋莉开卡车帮她运红茶过来。
红茶其实是编好号了的,每个红茶都用一个非负整数来编号,从 000 开始一直到正无穷。帕秋莉请来好朋友魔理沙,帮她一起运红茶。
一开始卡车上已经有了编号为 000 到 aaa 的红茶(注意 a=−1a=-1a=−1 就表示初始卡车上没有任何红茶),然后接下来到红魔馆的路上有 mmm 个时刻,每个时刻都会发生一种事件。
由于描述这些事件实在是太麻烦了,聪明的魔理沙用了一个长度为 mmm 的整数序列 ppp 来描述每个时刻发生的事件。
如果某个时刻的事件被忽视,那么我们不执行对应的操作,也不计算此时的答案。
帕秋莉是一个勤奋的人,每个时刻过后,如果这个时刻 iii 发生了事件(如果一个时刻发生的事件被忽视了,就不认为这个时刻发生了事件),令 ansians_iansi 表示时刻 iii 过后卡车上所有编号小于 ansians_iansi 的红茶都出现了,而编号为 ansians_iansi 的红茶没有出现(很显然这个值是唯一的)。当然如果时刻 iii 没有发生事件,则令 ansi=0ans_i=0ansi=0 。
请你对于 1≤i≤m1 \leq i \leq m1≤i≤m 计算出 ansi×(i2+7i) mod 998244353ans_i\times (i^2+7i)\ mod\ 998244353ansi×(i2+7i) mod 998244353 的异或和。
输入格式
第一行一个整数 TTT ,表示数据组数。
接下来有 TTT 行,每行表示一组数据。
每组数据依次有 m,seed,a,b,c,dm,\mathrm{seed},a,b,c,dm,seed,a,b,c,d 六个整数,其中 m,a,bm,a,bm,a,b 的意义与题面中相同;
ddd 表示是否只考虑第一种事件:ddd 的取值为 000 或 111 ,为特殊参数。当 d=1d=1d=1 时,请忽视所有的第二种事件与第三种事件(忽视的含义见题面描述)。
seed,c\mathrm{seed},cseed,c 是随机数生成器的参数。我们使用如下实现的随机数生成器 randnum()\mathrm{randnum}()randnum()。每组数据输入该组数据中 seed\mathrm{seed}seed 的初始值。
unsigned 32bit integer seed function randnum() seed = seed xor (seed lsh 13) seed = seed xor (seed rsh 17) seed = seed xor (seed lsh 5) return seed end function
计算 p[]p[]p[] 的代码如下:
for i = 1 to m by step 1 if randnum() mod c == 0 then p[i] = -1 else p[i] = randnum() mod b end if end for
我们在「数据范围与提示」的最后提供了这道题的一个输入输出模板(也可以在附加文件中下载),如果你不需要,请忽视它。
输出格式
每组数据输出一行表示答案。
样例
样例输入
1 7 327711436 4 6 3 0
样例输出
292
样例解释
ppp 序列为[5,−1,2,−1,2,5,4][5,-1,2,-1,2,5,4][5,−1,2,−1,2,5,4] 。初始时卡车上已经有了编号为 [0,4][0,4][0,4] 的红茶。
第一个时刻,发生第一种事件,编号为 555 的红茶加入卡车,此时卡车上编号为 [0,5][0,5][0,5] 的红茶都有,而编号为 666 的红茶没有,因此 ans1=6ans_1=6ans1=6 。
第二个时刻,理论上应该发生第三种事件,但是并没有红茶飞出了卡车,因此该事件被忽视, ans2=0ans_2=0ans2=0 。
第三个时刻,发生第二种事件,编号为 222 的红茶飞出卡车,此时卡车上编号为 [0,1][0,1][0,1] 的红茶都有,而编号为 222 的红茶没有,因此 ans3=2ans_3=2ans3=2 。
第四个时刻,发生第三种事件,魔理沙捡回编号为 222 的红茶回卡车,此时与第一个时刻后情况一致,因此 ans4=6ans_4=6ans4=6 。
第五个时刻和第三个时刻一致,因此 ans5=2ans_5=2ans5=2 。
第六个时刻,发生第二种事件,编号为 555 的红茶飞出卡车,此时卡车上编号为 0,1,3,40,1,3,40,1,3,4 的红茶都有,而编号为 2,52,52,5 的红茶没有,因此 ans6=2ans_6=2ans6=2 。
第七个时刻,发生第二种事件,编号为 444 的红茶飞出卡车,此时卡车上编号为 0,1,30,1,30,1,3 的红茶都有,而编号为 2,4,52,4,52,4,5 的红茶没有,因此 ans7=2ans_7=2ans7=2 。
更多样例
请在页面上方的附加文件中下载。
数据范围与提示
本题 C/C++ 时限 2.5 秒,Pascal 时限 5 秒。最后将改时限重测所有 Pascal 提交。
对于所有数据,1≤m≤1061 \leq m \leq 10^61≤m≤106,1≤T≤501 \leq T \leq 501≤T≤50 , −1≤a≤m-1 \leq a \leq m−1≤a≤m , 1≤b≤2×m1 \leq b \leq 2\times m1≤b≤2×m , 1≤c≤1071 \leq c \leq 10^71≤c≤107 , 0≤d≤10 \leq d \leq 10≤d≤1 。
ddd 表示是否只考虑第一种事件:ddd 的取值为 000 或 111 ,为特殊参数。当 d=1d=1d=1 时,请忽视所有的第二种事件与第三种事件(忽视的含义见题面描述)。
注意,d=1d=1d=1 时原本合法的事件也要被忽视,故即使你没有用到这个性质,也要记得判断 d=1d=1d=1 的情况。除测试点 777 以外的测试点也有可能出现 d=1d=1d=1 的数据。
先附一个和本题无关的歌词:
虹铃响.芳华绚.龙眠殿前;书阁自锁.七曜圣贤;钟停魅影骤现.幼月君临不夜. 绯色禁花.谁可哀怜;无赦白楼双剑.樱下华胥永眠;彼岸红.可惜身命渡黄泉;是非曲直.净罪六十年;恨不灭.白发红颜;知天命.情系人间;千年月贤壶中术逆苍天.蓬莱玉枝映辉月;
飞翔天.天狐念.颠覆境界;因幡白帝.仙兔幻眼;碎月醉梦集结.摄命风靡红叶;花映幽冢.香颂遍野;福祸转.秋山瀑悬;分沧海.奇迹重现;天水源.神德未改信仰湮;乾坤不变.蛙鸣风雨远;龙鱼泳.羽衣紫电;大地动.绯想无念;三足金乌.星陨地心灵殿;命苦短.空余白莲;红白玉.二色花蝶;雨霖铃.洒落星屑;幻梦终醒.本无不散之宴;却不悔,付此华年!!!
1 #include<bits/stdc++.h> 2 #define Min(a,b) (a) < (b) ? (a) : (b) 3 int h1,h2,t1,t2,it; 4 unsigned int ans_sum=0,cur_ans=0; 5 namespace IO{ 6 int c; 7 unsigned int seed; 8 unsigned int randnum(){ 9 seed^=seed<<13; 10 seed^=seed>>17; 11 seed^=seed<<5; 12 return seed; 13 } 14 15 inline int read(int &x){scanf("%d",&x);return x;} 16 inline void init_case(int &m,int &a,int &b,int &d,int p[]){ 17 scanf("%d%u%d%d%d%d",&m,&seed,&a,&b,&c,&d); 18 for(int i=1;i<=m;i++){ 19 if(randnum()%c==0)p[i]=-1; 20 else p[i]=randnum()%b; 21 } 22 } 23 24 inline void update_ans(unsigned int &ans_sum,unsigned int cur_ans,int no){ 25 const static unsigned int mod=998244353; 26 ans_sum^=(long long)no*(no+7)%mod*cur_ans%mod; 27 } 28 } 29 using IO::read; 30 using IO::init_case; 31 using IO::update_ans; 32 using namespace std; 33 int p[2000005], q1[2000005], q2[2000005]; 34 bitset<2000005> vis, ins; 35 int main(){ 36 int T;read(T); 37 int m,a,b,d; 38 while(T--){ 39 ans_sum = 0; cur_ans = 0; 40 init_case(m,a,b,d,p); 41 it = 0; b = max(a+1,b); 42 vis.reset(); ins.reset(); 43 for(int i=0;i<=a;i+=1) vis[i] = ins[i] = true; 44 while(vis[it]) it += 1; 45 h1 = 1, t1 = 0, h2 = 1, t2 = 0; 46 for(int i=1;i<=m;i++){ 47 if(p[i]!=-1 && !vis[p[i]]) { 48 vis[p[i]] = true; ins[p[i]] = true; 49 while(vis[it]) it += 1; 50 } else { 51 if(d) continue; 52 if(p[i]!=-1 && ins[p[i]]) { 53 ins[p[i]] = false; 54 while(h1<=t1 && q1[t1] > p[i]) t1 -= 1; 55 q1[++t1] = p[i]; q2[++t2] = p[i]; 56 } else { 57 if(h2>t2) continue; 58 if(h1<=t1 && q1[h1] == q2[h2]) h1 += 1; 59 ins[q2[h2]] = true; h2 += 1; 60 } 61 } 62 if(h1 <= t1) cur_ans = Min(it,q1[h1]); 63 else cur_ans = it; 64 update_ans(ans_sum,cur_ans,i); 65 } 66 printf("%u\n",ans_sum); 67 } 68 return 0; 69 }