题目背景
企鹅大陆是一片神奇的土地,在厚厚的冰层下埋藏着一个巨大的宝藏。探险家企鹅豆豆挖穿冰层到达了宝库,但他发现了一个令人发愁的问题。一共有五座宝库,每个宝库是由某些远古计算机控制的。由于年代久远,这些计算机里的程序已经消失不见了,只有给这些计算机重新填写代码并且顺利运行,输出了正确结果才能触发开门的机关。
题目描述
每一个宝库大门由一个计算机集群控制,计算机之间用数据线相连以便传输数据。但是有很多数据线已经损坏了,所以只留下了一部分连线。一开始数据线上没有数据,当一台计算机向数据线上写入时,数据线上就有了一个整数。每条数据线上最多可以同时传输一个整数,当整数被读取后便会消失,数据线就又回到没有数据的状态。
每台远古计算机有两个储存单元,分别名为 aa 和 bb,每个储存单元能够储存一个 -2147483648−2147483648 到 21474836472147483647 之间的整数。
每个时刻,每台远古计算机可以执行一条指令,一共有以下几种指令:
mov reg val
:将储存单元reg
的值赋值为val
的值;add reg val
:给储存单元reg
加上val
的值;dec reg val
:给储存单元reg
减去val
的值;mul reg val
:给储存单元reg
乘以val
的值;div reg val
:给储存单元reg
除以val
的值,这里的除法是向零取整的除法,如 \frac{-5}{2} = -22−5=−2;and reg val
:给储存单元reg
二进制与上val
的值;or reg val
:给储存单元reg
二进制或上val
的值;xor reg val
:给储存单元reg
二进制异或上val
的值;jmp val
跳转到整个程序第val
条语句,语句从程序开头开始,用从 11 开始的正整数计数;jz reg val
:如果reg
的值为 00,那么跳转到第val
行;jnz reg val
:如果reg
的值不为 00,那么跳转到第val
行;jgz reg val
:如果reg
的值严格大于 00,那么跳转到第val
行;jsz reg val
:如果reg
的值严格小于 00,那么跳转到第val
行;read x reg
:从远古计算机 xx 读取一个数到储存单元reg
当中,如果数据线上缓存了一个数字,将读取这个数字并返回,否则等待下个周期再次尝试读取。x = 0x=0 时视为从标准输入数据读取一个数;write val x
:将val
的数值向远古计算机 xx 方向所在数据线写入,当且仅当数据线上没有存有数据才会成功写入,否则等待下个周期再次尝试写入。x = 0x=0 时视为向标准输出数据写出一个数。
reg
表示一个储存单元,只能为 aa 或者 bb 之一。
val
表示一个储存单元或者一个数字的值,比如填入 aa 表示 aa 中储存的值或者填入 233233 表示 233233 这个数字。
一台远古计算机读写指令中 xx 只有与当前远古计算机直接有数据线相连,或者 x=0x=0 才被视为合法指令。
每台远古计算机的标准输入输出独立,远古计算机之间互不影响,即每台远古计算机都有独立的一个标准输入端和一个标准输出端。
每个周期计算时,所有需要执行 write
指令的远古计算机先计算,然后需要执行 read
指令的远古计算机再计算,需要执行其余指令的远古计算机最后计算。
在读取时,如果标准输入数据没有任何可以继续读取的数据,该远古计算机将进入永远等待状态。
一台远古计算机如果执行完了最后一条指令,将会重新从第一条指令开始执行。
如果一台远古计算机没有任何指令,该计算机将永远处于等待状态。
指令计数是从 11 开始的正整数。
一条数据线上最多只能暂存一个数据,两台计算机之间只有一条数据线,即可能读取自己上一轮写入的数据,如果两端的远古计算机同时读取或写入同一条数据线上的 数据,结果将不可预知。
不存在写入标准输入的方法或是从标准输出当中读取数据的方法。
比如如下样例是从 11 号计算机的标准输入读入两个数,并从 22 号计算机的标准输出输出两个数之和。
node 1
read 0 a
read 0 b
write a 2
write b 2
node 2
read 1 a
read 1 b
add a b
write a 0
而以下写法是错误的
node 1
read 0 a
read 0 b
add a b
write a 0
node 2
mov a a
因为正确答案中,一号远古计算机的标准输出为空,而二号远古计算机的标准输出才是两个数之和。
子任务
子任务 1
11 号远古计算机的标准输入将会有不超过 100100 个非负整数,按照原顺序输出到 11 号远古计算机的输出当中。
子任务 2
11 号远古计算机一个非负整数 kk,按照原输入顺序将斐波那契数列第 kk 项输出到 11 号点的标准输出当中,输入数据保证第 kk 项不超过 10^9109。斐波那契数列通项公式为 F_0 = 0, F_1 = 1, F_n = F_{n-1} + F_{n-2}(2 \le n)F0=0,F1=1,Fn=Fn−1+Fn−2(2≤n)。
子任务 3
11 号远古计算机的标准输入将会有不超过 100100 个非负整数,按照原顺序输出到 nn 号远古计算机的输出当中。
子任务 4
第 11 到 5050 号远古计算机分别输入 11 个数,将这 5050 个数从 5151 到 100100 号远古计算机输出,输出顺序任意,每个远古计算机输出数字个数任意。
子任务 5
第 11 到 1010 号远古计算机各输入 11 个数,将这些数对应从 100100 到 9191 号远古计算机输出,即 ii 号点输入的数需要从 101 - i101−i 号点输出。
输入格式
这是一道提交答案题,共有 55 组输入数据,这些数据命名为 oldcomputer1.in
~ oldcomputer5.in
。
这些文件描述了远古计算机之间的连线状态。
文件的第一行是三个非负整数 x,nx,n 和 mm,表示测试点编号、远古计算机的个数与他们之间的连线条数,远古计算机是从 11 到 nn 标号的。
接下来 mm 行,每行两个正整数 x, yx,y,表示计算机 xx 和计算机 yy 之间通过数据线直接相连。
输出格式
对于每组输入数据,你需要提交相应的输出文件 oldcomputer1.out
~ oldcomputer5.out
。
这些文件描述了每台远古计算机的代码内容。
文件由多个代码块组成,每个代码块的具体格式如下:
第一行为一个字符串 node
与一个 11 到 nn 之间的整数 aa,由一个空格隔开,表示接下来是计算机 aa 的指令。
接下来多行为该计算机的具体指令内容。
每台计算机的指令应当最多出现一次,否则将会出现未知错误。
所有计算机的指令总条数应当不超过 10^6106 行。
输入输出样例
无
说明/提示
评分方式
对于每个测试点,有三个参数 a_1, a_2, a_3a1,a2,a3。
如果选手提交的代码在 a_1a1 个周期内正确输出了答案,将会得到该测试点 100\%100% 的分。
如果选手提交的代码在 a_2a2 个周期内正确输出了答案,将会得到该测试点 60\%60% 的分。
如果选手提交的代码在 a_3a3 个周期内正确输出了答案,将会得到该测试点 30\%30% 的分。
即在每个周期结束时,会分别进行一次答案正确性判断,以最早正确的一次为准。
子任务分值
子任务编号 | 11 | 22 | 33 | 44 | 55 |
---|---|---|---|---|---|
集训队分值 | 1010 | 1515 | 1515 | 3030 | 3030 |
非集训队分值 | 2020 | 2020 | 2020 | 2020 | 2020 |
看到题目就晕了
题目就比我前面的两篇文章长。
但仔细看题,好像要用到的就read,write,add,jmp
可我不知道要怎么做
任务1
任务1我借鉴了一小下,发现很简单(是借鉴思路,代码是我敲的!!!)
#include<bits/stdc++.h>
using namespace std;
int main(){
freopen("oldcomputer1.out","w",stdout);
printf("node 1\nread 0 a\nwrite a 0");
return 0;
}
简单吧!
so easy!!
任务2
颜色变了
这个也不会很难
主要是那代码中的代码是什么
这是我的:
#include<bits/stdc++.h>
using namespace std;
int main(){
freopen("oldcomputer1.out","w",stdout);
printf("node 1\nread 0 a\nadd a 4\njmp a\n");
return 0;
}
后面还要有write
这是一个斐波那契数列
需要一个O(1)的代码
#include<bits/stdc++.h>
using namespace std;
int main(){
freopen("oldcomputer2.out","w",stdout);
printf("node 1\nread 0 a\nadd a 4\njmp a\n");
int f[45];
f[0]=0;f[1]=1;
for(int i=2;i<=45;i++)
f[i]=f[i-1]+f[i-2];
for(int i=0;i<=45;i++)
printf("write %d 0\n",f[i]);
return 0;
}
OK啦!
任务三
不知道这个颜色会不会太淡
任务三不会写
我当然会去借鉴啦
好像要用单路传输
(-。-;)
还是不会
呵呵(哭笑不得)
#include<bits/stdc++.h>
using namespace std;
const int N=110;
vector<int> g[N];
bool inq[N];
int dis[N],pre[N],n,m;
void spfa()
{
memset(dis,0x3f,sizeof(dis));
queue<int> q;
q.push(1);dis[1]=0;
while(!q.empty())
{
int u=q.front();
for(int v : g[u])
if(dis[u]+1<dis[v])
{
pre[v]=u;
dis[v]=dis[u]+1;
if(inq[v]) continue;
inq[v]=1;q.push(v);
}
q.pop();inq[u]=0;
}
for(int i=n,nxt=0;i;i=pre[i])
{
printf("node %d\n",i);
printf("read %d a\n",pre[i]);
printf("write a %d\n",nxt);
nxt=i;
}
}
int main()
{
freopen("oldcomputer3.in","r",stdin);
freopen("oldcomputer3.out","w",stdout);
int qwq;
scanf("%d%d%d",&qwq,&n,&m);
for(int i=1,u,v;i<=m;i++)
{
scanf("%d%d",&u,&v);
g[u].push_back(v);
g[v].push_back(u);
}
spfa();
}
放上答案就对了
这是98版!
在这吃了亏
后面我可能都不会,,ԾㅂԾ,,
#include<bits/stdc++.h>
using namespace std;
typedef pair<int,int> pii;
const int N=1010;
vector<int> g[N];
vector<pii> msg[N];
int dis[N],n,m;
bool inq[N];
void spfa()
{
queue<int> q;
memset(dis,0x3f,sizeof(dis));
for(int i=51;i<=100;i++)
{
dis[i]=0;
inq[i]=1;
q.push(i);
}
while(!q.empty())
{
int u=q.front();
for(int v : g[u])
if(dis[u]+1<dis[v])
{
dis[v]=dis[u]+1;
if(inq[v]) continue;
inq[v]=1;q.push(v);
}
q.pop();inq[u]=0;
}
}
int main()
{
freopen("oldcomputer4.in","r",stdin);
freopen("oldcomputer4.out","w",stdout);
int qwq;
scanf("%d%d%d",&qwq,&n,&m);
for(int i=1,u,v;i<=m;i++)
{
scanf("%d%d",&u,&v);
g[u].push_back(v);
g[v].push_back(u);
}
spfa();
queue<int> q;
for(int i=1;i<=50;i++)
{
q.push(i);
msg[i].push_back(pii(0,0));
}
while(!q.empty())
{
int u=q.front(),v=0;q.pop();
for(int vv : g[u]) if(dis[u]==dis[vv]+1) v=vv;
printf("node %d\n",u);
sort(msg[u].begin(),msg[u].end());
for(pii pr : msg[u])
{
printf("read %d a\n",pr.second);
printf("write a %d\n",v);
msg[v].push_back(pii(pr.first+1,u));
}
if(v) q.push(v);
}
return 0;
}
#include<bits/stdc++.h>
using namespace std;
const int N=210;
struct MSG{int from,to,time;};
vector<int> g[N];
vector<MSG> msg[N];
bool bad[N][N],inq[N];
int dis[N],pre[N],n,m,ans=0;
bool operator < (const MSG &a,const MSG &b){return a.time<b.time;}
void spfa(int s,int t)
{
memset(pre,0,sizeof(pre));
memset(dis,0x3f,sizeof(dis));
queue<int> q;q.push(s);
dis[s]=0;inq[s]=1;
while(!q.empty())
{
int u=q.front();
for(int v : g[u])
{
int w=dis[u]+1;
while(bad[v][w]||bad[v][w+1]) w++;
if(w<dis[v])
{
dis[v]=w;pre[v]=u;
if(inq[v]) continue;
inq[v]=1;q.push(v);
}
}
q.pop();inq[u]=0;
}
for(int i=t,nxt=0;i;i=pre[i])
{
bad[i][dis[i]]=bad[i][dis[i]+1]=1;
msg[i].push_back((MSG){pre[i],nxt,dis[i]});
nxt=i;
}
ans=max(ans,dis[t]);
}
int main()
{
freopen("oldcomputer5.in","r",stdin);
freopen("oldcomputer5.out","w",stdout);
int qwq;
scanf("%d%d%d",&qwq,&n,&m);
for(int i=1,u,v;i<=m;i++)
{
scanf("%d%d",&u,&v);
g[u].push_back(v);
g[v].push_back(u);
}
for(int i=1;i<=10;i++) bad[i][0]=bad[i][1]=1;
for(int i=1;i<=10;i++) spfa(i,101-i);
for(int i=1;i<=n;i++)
{
if(msg[i].empty()) continue;
sort(msg[i].begin(),msg[i].end());
printf("node %d\n",i);
for(MSG pp : msg[i])
{
printf("read %d a\n",pp.from);
printf("write a %d\n",pp.to);
}
}
cerr<<ans+2<<endl;
return 0;
}
记得关注哦